我有一个在SQL Fiddle中完美运行的查询:http://sqlfiddle.com/#!9/ffcba/22但是当我在我的生产服务器上尝试它时,在@user = user时@row_number没有递增的意义上它不起作用最终得到以下结果:
+------+-------+-----+---------+
| user | file | log | billing |
+------+-------+-----+---------+
| 1 | b.pdf | 3 | 1 |
| 1 | b.pdf | 3 | 1 |
| 1 | a.pdf | 2 | 0 |
| 2 | d.pdf | 2 | 1 |
| 2 | d.pdf | 2 | 1 |
| 2 | c.pdf | 1 | 0 |
| 3 | f.pdf | 3 | 0 |
| 3 | e.pdf | 1 | 0 |
| 4 | g.pdf | 0 | 1 |
| 4 | i.pdf | 2 | 1 |
| 4 | g.pdf | 0 | 1 |
| 4 | j.pdf | 3 | 0 |
| 4 | i.pdf | 2 | 1 |
| 4 | h.pdf | 1 | 0 |
+------+-------+-----+---------+
...而不是小提琴归结为的4行结果,这应该是它应该是什么。小提琴是一个测试,虽然我的生产变量略有不同,但我最终还是从小提琴复制模式来构建测试表,以确认所有内容,据我所知,完全相同。我目前正在运行MySQL 5.6.23,而小提琴正在下拉列表中使用5.6。
似乎在小提琴上正确运行以下设置:
架构:
create table tests ( ID int, user int, log int);
insert into tests values
( 1, 1, 2),
( 2, 1, 2),
( 3, 2, 2),
( 4, 3, 2),
( 5, 3, 2),
( 6, 4, 2);
create table files (ID int, file varchar(10), log int, billing int, user int);
insert into files values
( 1, 'a.pdf', 2, 0, 1),
( 2, 'b.pdf', 3, 1, 1),
( 3, 'c.pdf', 1, 0, 2),
( 4, 'd.pdf', 2, 1, 2),
( 5, 'e.pdf', 1, 0, 3),
( 6, 'f.pdf', 3, 0, 3),
( 7, 'g.pdf', 0, 1, 4),
( 8, 'h.pdf', 1, 0, 4),
( 9, 'i.pdf', 2, 1, 4),
( 10, 'j.pdf', 3, 0, 4)
查询
SELECT user, file, log, billing
FROM (
SELECT @row_number:=CASE WHEN @user=user THEN @row_number+1
ELSE 1
END AS row_number,
@user:=user AS user,
file, log, billing
FROM (
SELECT 1 AS pri, t.user, f.file, f.log, f.billing
FROM (SELECT DISTINCT user, log
FROM tests
WHERE log = 2) AS t
INNER JOIN files AS f
ON (t.user = f.user AND t.log = f.log AND f.billing = 1)
UNION ALL
SELECT 2 AS pri, t.user, f.file, f.log, f.billing
FROM (SELECT DISTINCT user, log
FROM tests
WHERE log = 2) AS t
INNER JOIN files AS f
ON (t.user = f.user AND f.billing = 1)
WHERE f.log > t.log OR f.log = 0
UNION ALL
SELECT 3 AS pri, t.user, f.file, f.log, f.billing
FROM (SELECT DISTINCT user, log
FROM tests
WHERE log = 2) AS t
INNER JOIN files AS f ON (t.user = f.user)
ORDER BY user, pri, log DESC ) s ) r
WHERE r.row_number = 1
ORDER BY user
小提琴所需的结果
+------+-------+-----+---------+
| user | file | log | billing |
+------+-------+-----+---------+
| 1 | b.pdf | 3 | 1 |
| 2 | d.pdf | 2 | 1 |
| 3 | f.pdf | 3 | 0 |
| 4 | i.pdf | 2 | 1 |
+------+-------+-----+---------+
如果有人知道为什么这可能不起作用的任何原因,也许是一个设置或其他什么,任何有关纠正它的见解将不胜感激
谢谢!
答案 0 :(得分:1)
当您尝试在修改它时在同一个选择中读取变量时,MySQL结果是不确定的。
对于其他语句,例如SELECT,您可能会得到结果 期待,但这不能保证。在以下声明中,您 可能会认为MySQL会首先评估@a然后做一个 第二个任务:
SELECT @ a,@ a:= @ a + 1,...;但是,评估顺序为 涉及用户变量的表达式是未定义的。
为了解决这个问题,我们可以使用嵌套的条件语句来强制执行顺序。您应该尝试做的是将case
语句更改为嵌套的if
语句。
所以改变这个:
SELECT @row_number:=CASE WHEN @user=user THEN @row_number+1 -- do i happen first?
ELSE 1
END AS row_number,
@user:=user AS user, -- or do i?
哪个地方可能遇到麻烦 - 我们不知道首先会评估case
或@user := user
,对此:
select if(@user = user, -- if we are processing the same user
@row_number := @row_number + 1, -- increment row number
if(@user := user, -- otherwise set current user
@row_number := 1, -- then set row number to 1
@row_number := 1)) as row_number, -- failsafe if user is null
user,
file, log, billing
ifs
链将确保您的变量包含您期望的值。
我修改了你的小提琴here,你可以看到结果与之前的结果相同,但它们应该更加可靠。请尝试使用其他数据,看看它是如何进行的。
此外,变量未初始化,这是需要发生的事情。你可以通过在查询之前在语句中明确设置它们来做到这一点,或者你可以cross join
到一个简单的选择来设置它们 - 我倾向于选择后者。
cross join (select @row_number := 1, @user := 0) q