我正试图帮助解决这个问题 Selecting rows based on a few rules
想法是为每个用户选择语言匹配@lenguage 的行 ID,否则选择创建的第一种语言。
因为没有row_number()
,不得不使用用户变量。假设我添加了一个字段 test_id
,这样就可以将所有案例放在同一个表中。
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
关于mysql - 用变量模拟 row_number 忽略顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57317471/