用变量模拟 row_number 忽略顺序
simulate row_number with variables ignore order
我正试图帮助解决这个问题Selecting rows based on a few rules
这个想法是为每个用户 select 行 ID 与语言匹配 @lenguage 否则 select 创建的第一种语言。
因为没有row_number()
,不得不使用用户变量。考虑我添加一个字段 test_id
这样可以将所有案例放在同一个 table.
SELECT t.* , (`language` = @language) as tt,
@rn := if (@partition = CONCAT(`test_id`, '-', `user`),
@rn + 1,
if(@partition := CONCAT(`test_id`, '-', `user`), 1, 1)
) as rn,
@partition
FROM Table1 t
CROSS JOIN ( SELECT @language := 'de', @rn := 0, @partition := '' ) as var
ORDER BY CONCAT(`test_id`, '-', `user`),
(`language` = @language) DESC,
`created`
输出
但即使 ORDER BY
给出了正确的排序,分区 1-4
和 3-4
也不会将语言 'de'
放在第一位。所以有些东西正在改变变量 @rn
的分配方式。
| test_id | id | title | language | created | user | tt | rn | @partition |
|---------|----|-------|----------|----------------------|------|----|----|------------|
| 1 | 3 | c | de | 2019-01-03T00:00:00Z | 4 | 1 | 3*| 1-4 |
| 1 | 1 | a | en | 2019-01-01T00:00:00Z | 4 | 0 | 1 | 1-4 |
| 1 | 2 | b | es | 2019-01-02T00:00:00Z | 4 | 0 | 2 | 1-4 |
| 2 | 1 | a | en | 2019-01-01T00:00:00Z | 4 | 0 | 1 | 2-4 |
| 2 | 2 | b | es | 2019-01-02T00:00:00Z | 4 | 0 | 2 | 2-4 |
| 3 | 1 | a | en | 2019-01-01T00:00:00Z | 3 | 0 | 1 | 3-3 |
| 3 | 3 | b | de | 2019-01-03T00:00:00Z | 4 | 1 | 2*| 3-4 |
| 3 | 2 | b | es | 2019-01-02T00:00:00Z | 4 | 0 | 1 | 3-4 |
| 3 | 4 | c | de | 2019-01-04T00:00:00Z | 5 | 1 | 1 | 3-5 |
选择所有行后完成排序。您的 @rn
变量是在行选择期间设置的,因此它使用的是行的内部顺序,而不是您的 ORDER BY
子句中指定的顺序。
您需要将排序移动到子查询中,然后在主查询中计算 @rn
。
SELECT t.*,
@rn := if (@partition = CONCAT(`test_id`, '-', `user`),
@rn + 1,
if(@partition := CONCAT(`test_id`, '-', `user`), 1, 1)
) as rn,
@partition
FROM (
SELECT *, (language = @language) AS tt
FROM Table
CROSS JOIN (SELECT @language := 'de') AS var
ORDER BY CONCAT(test_id, '-', user),
tt DESC,
created
) AS t
CROSS JOIN ( SELECT @rn := 0, @partition := '' ) as var
我正试图帮助解决这个问题Selecting rows based on a few rules
这个想法是为每个用户 select 行 ID 与语言匹配 @lenguage 否则 select 创建的第一种语言。
因为没有row_number()
,不得不使用用户变量。考虑我添加一个字段 test_id
这样可以将所有案例放在同一个 table.
SELECT t.* , (`language` = @language) as tt,
@rn := if (@partition = CONCAT(`test_id`, '-', `user`),
@rn + 1,
if(@partition := CONCAT(`test_id`, '-', `user`), 1, 1)
) as rn,
@partition
FROM Table1 t
CROSS JOIN ( SELECT @language := 'de', @rn := 0, @partition := '' ) as var
ORDER BY CONCAT(`test_id`, '-', `user`),
(`language` = @language) DESC,
`created`
输出
但即使 ORDER BY
给出了正确的排序,分区 1-4
和 3-4
也不会将语言 'de'
放在第一位。所以有些东西正在改变变量 @rn
的分配方式。
| test_id | id | title | language | created | user | tt | rn | @partition |
|---------|----|-------|----------|----------------------|------|----|----|------------|
| 1 | 3 | c | de | 2019-01-03T00:00:00Z | 4 | 1 | 3*| 1-4 |
| 1 | 1 | a | en | 2019-01-01T00:00:00Z | 4 | 0 | 1 | 1-4 |
| 1 | 2 | b | es | 2019-01-02T00:00:00Z | 4 | 0 | 2 | 1-4 |
| 2 | 1 | a | en | 2019-01-01T00:00:00Z | 4 | 0 | 1 | 2-4 |
| 2 | 2 | b | es | 2019-01-02T00:00:00Z | 4 | 0 | 2 | 2-4 |
| 3 | 1 | a | en | 2019-01-01T00:00:00Z | 3 | 0 | 1 | 3-3 |
| 3 | 3 | b | de | 2019-01-03T00:00:00Z | 4 | 1 | 2*| 3-4 |
| 3 | 2 | b | es | 2019-01-02T00:00:00Z | 4 | 0 | 1 | 3-4 |
| 3 | 4 | c | de | 2019-01-04T00:00:00Z | 5 | 1 | 1 | 3-5 |
选择所有行后完成排序。您的 @rn
变量是在行选择期间设置的,因此它使用的是行的内部顺序,而不是您的 ORDER BY
子句中指定的顺序。
您需要将排序移动到子查询中,然后在主查询中计算 @rn
。
SELECT t.*,
@rn := if (@partition = CONCAT(`test_id`, '-', `user`),
@rn + 1,
if(@partition := CONCAT(`test_id`, '-', `user`), 1, 1)
) as rn,
@partition
FROM (
SELECT *, (language = @language) AS tt
FROM Table
CROSS JOIN (SELECT @language := 'de') AS var
ORDER BY CONCAT(test_id, '-', user),
tt DESC,
created
) AS t
CROSS JOIN ( SELECT @rn := 0, @partition := '' ) as var