mysql的用户变量疑问

ice_berg16 2006-08-14 04:19:04
mysql的用户变量是如何工作的?

假设有如下sql
set @cnt=0;
select @cnt:=@cnt+1,tbl.*
from tbl
会得到类似下面的数据
@cnt:=@cnt+1 | id | cid | name |
+--------------+----+-----+-------------+
| 1 | 1 | 1 | post1-1-1 |
| 2 | 2 | 1 | post1-2-2 |
| 3 | 3 | 1 | post1-3-3 |
| 4 | 4 | 1 | post1-4-4 |
| 5 | 5 | 1 | post1-5-5 |
| 6 | 6 | 2 | post2-1-6 |
| 7 | 7 | 2 | post2-2-7 |
| 8 | 8 | 3 | post3-1-8 |

而使用
set @cnt=0;
select @cnt:=@cnt+1,tbl.*
from tbl
where @cnt=1;则没有记录输出
如果条件改成@cnt=0则会输出第一条记录,不知道MYSQL是计算处理变量的
...全文
260 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
Gdj 2006-08-16
  • 打赏
  • 举报
回复
狮屎胜于熊便。现实与手册有冲突以现实为主。
在我的版本上表达式先计算了,然后having,表达式再次计算。4.0版的。
ice_berg16 2006-08-16
  • 打赏
  • 举报
回复
手册上那块我看过好几遍了,不过还是很迷惑,手册上这么说:
----------------------
HAVING子句基本上是最后使用,只位于被发送给客户端的条目之前,
表达式发送到客户端后才进行计算
----------------------
这样看来having应该先执行,再计算表达式。不过这样好像不合理哦,而且结果也不是这样的。
stzjzs 2006-08-15
  • 打赏
  • 举报
回复
SET @cnt =0;
select @cnt:=@cnt+1 as haha,post.*
from post HAVING haha=2


mysql-5.0.13-rc-win32 在 phpMyAdmin 2.7.0-pl2 sql中可以正确执行
Gdj 2006-08-15
  • 打赏
  • 举报
回复
SET @cnt =0;
select @cnt:=@cnt+1 as ttt,post.*
from post having ttt =1

having是在结果出来后再次执行sql的。
当ttt=1时,会再次执行@cnt:=@cnt+1,所以显示的ttt就=2了。不过数据其实还是第一条。
Gdj 2006-08-15
  • 打赏
  • 举报
回复
建议使用子查询

select * from (select @cnt:=@cnt+1 as ttt,post.* from post) where ttt=1;
Gdj 2006-08-15
  • 打赏
  • 举报
回复
这不是很正常吗?没发现有什么可疑的地方?

如果
set @cnt=0
当执行where @cnt=1时,@cnt=0,所以不会有任何结果。@cnt=@cnt+1是有结果时才会执行的。

ice_berg16 2006-08-15
  • 打赏
  • 举报
回复
上面的说错了,
SET @cnt =0;
select @cnt:=@cnt+1 as ttt,post.*
from post having ttt =1;
的结果是
ttt全部+1,郁闷
ice_berg16 2006-08-15
  • 打赏
  • 举报
回复
你测试通过了吗?我怎么没有
SET @cnt =0;
select @cnt:=@cnt+1 as ttt,post.*
from post having ttt =1;
得出的结果是除了ttt=1的结果,很奇怪
而having ttt =2则没有结果

环境是mysql5.0
zeroleonhart 2006-08-15
  • 打赏
  • 举报
回复
SET @cnt =0;
select @cnt:=@cnt+1 as haha,post.*
from post HAVING haha=2


mysql-5.0.13-rc-win32 在 phpMyAdmin 2.7.0-pl2 sql中可以正确执行

-------------------------------------------------------------

语法没问题,但不会有返回值,所以不能算是正确执行
zeroleonhart 2006-08-15
  • 打赏
  • 举报
回复
按照这个解释:
select @cnt:=@cnt+1,tbl.* from tbl where @cnt=1;
就的确不会有返回值,因为@cnt是在客户端才被加1的,而查询的时候,只有@cnt=0一条记录
我运行:
SELECT @cnt := @cnt +1, tbl. * FROM tbl WHERE @cnt =0;
的确只返回了一条。
而运行
SELECT @cnt := @cnt +1, tbl.* FROM tbl having @cnt =1;
是不会有返回值的,因为运行查询的时候@cnt还没有+1。
zeroleonhart 2006-08-15
  • 打赏
  • 举报
回复
I find this from mysql manual :

----------------------------------------------

注意:在一个 SELECT 语句中,各个表达式只有在它被送到客户端时才能被求值。这就意味着,在 HAVING、GROUP BY 或 ORDER BY 子句中,你不能使用一个包含在 SELECT 部份所设置变量的表达式。例如:下面的语句将不会按预期的运作:

mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM table_name HAVING b=5;

原因是因为 @aa 不会是当前行的值,而是前一个符合条件的行的 id 值。

规则就是在同一语句中决不赋值 和 使用同一个变量。
Gdj 2006-08-15
  • 打赏
  • 举报
回复
“having是在结果出来后再次执行sql的”
这句话是错误的

在我们看来,你是错误的。因为在我们的版本用having后的确是再次执行了@cnt=:@cnt+1。
所以having的写法不建议使用。每一个版本都返回不同结果的语句敢用吗?
xuzuning 2006-08-15
  • 打赏
  • 举报
回复
有问题吗?那肯定是你的mysql的版本问题了!
我的是mysql 4.0.20,由于其他应用项目的约束,只能用这个了

“having是在结果出来后再次执行sql的”
这句话是错误的

having 子句是在查询结果中过滤出符合条件的记录

对于
SET @cnt =0;
select @cnt:=@cnt+1 as ttt,post.*
from post
having ttt =1;

将先执行
select @cnt:=@cnt+1 as ttt,post.*
from post
得到
ttt ...
1 ...
2 ...
3 ...
然后在此结果中提取 ttt=1 的记录并返回
Gdj 2006-08-15
  • 打赏
  • 举报
回复
估计是版本问题。我这里出来的是只有第一条,但显示为2。
ice_berg16 2006-08-15
  • 打赏
  • 举报
回复
SET @cnt =0;
select @cnt:=@cnt+1 as ttt,post.*
from post having ttt =1

having是在结果出来后再次执行sql的。
当ttt=1时,会再次执行@cnt:=@cnt+1,所以显示的ttt就=2了。不过数据其实还是第一条。

那为什么出来的还是所有的数据,而不是第一条?
stzjzs 2006-08-14
  • 打赏
  • 举报
回复
受 xuzuning(唠叨) 启示

SET @cnt =0;
select @cnt:=@cnt+1 as haha,tbl.*
from tbl HAVING haha=2

mysql测试通过

唠叨的第三点可能手误 select @cnt:=@cnt+1 as cnt,tbl.* from tbl HAVING cnt=1
xuzuning 2006-08-14
  • 打赏
  • 举报
回复
1、select @cnt:=@cnt+1,tbl.* from tbl
返回的第一个列名为 @cnt:=@cnt+1
显然他不能作为列名出现在where子句中

2、若写做 select @cnt:=@cnt+1 as cnt,tbl.* from tbl
但cnt同样不能出现在where子句中

3、但是 select @cnt:=@cnt+1,tbl.* from tbl HAVING cnt=1
就可以了

21,886

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧