尝试利用https://stackoverflow.com/a/123481中的技术,我尝试使用特定的排序方式为每个name
检索一行,即按{{1降序排序后的第一行/第一行}},active
,然后是created
。但是,prid
列可能包含数字或active
值,这导致在NULL
情况下重复。任何帮助将不胜感激。
源表:
name=bat
所需结果:
+------+-------+--------+---------+
| prid | name | active | created |
+------+-------+--------+---------+
| 1 | bat | NULL | 3 |
| 2 | bat | 1 | 2 |
| 3 | bat | 2 | 1 |
| 4 | bat | 3 | 0 |
| 5 | noise | NULL | 2 |
| 6 | noise | NULL | 1 |
| 7 | cup | NULL | 0 |
| 8 | cup | NULL | 0 |
| 9 | egg | 4 | 4 |
| 10 | egg | 4 | 2 |
+------+-------+--------+---------+
SQL:
+------+-------+--------+---------+
| prid | name | active | created |
+------+-------+--------+---------+
| 9 | egg | 4 | 4 |
| 4 | bat | 3 | 0 |
| 5 | noise | NULL | 2 |
| 8 | cup | NULL | 0 |
+------+-------+--------+---------+
实际结果:
SELECT p1.*
FROM source_table p1
LEFT JOIN source_table p2 ON (
p1.name = p2.name
AND (
p1.active < p2.active
OR (
(p1.active = p2.active OR (p1.active IS NULL AND p2.active IS NULL))
AND (
p1.created < p2.created
OR (
p1.created = p2.created AND p1.prid < p2.prid
)
)
)
)
)
WHERE p2.prid IS NULL
ORDER BY p1.active DESC, p1.created DESC, p1.prid DESC
@Gordon Linoff
感谢您的帮助,我尝试使用索引为+------+-------+--------+---------+
| prid | name | active | created |
+------+-------+--------+---------+
| 9 | egg | 4 | 4 |
| 4 | bat | 3 | 0 |
| 1 | bat | NULL | 3 |
| 5 | noise | NULL | 2 |
| 8 | cup | NULL | 0 |
+------+-------+--------+---------+
和(name, active, created, prid)
的第二个版本,但是运行起来很慢。
这需要1秒钟,返回正确的结果,但是顺序错误:
(active, created, prid)
这需要55秒:
SELECT t1.prid
FROM source_table t1
WHERE t1.prid = (
SELECT t2.prid
FROM source_table t2
WHERE t2.name = t1.name
ORDER BY t2.active DESC, t2.created DESC, t2.prid DESC
LIMIT 1
)
LIMIT 50
我真的需要SELECT t1.prid
FROM source_table t1
WHERE t1.prid = (
SELECT t2.prid
FROM source_table t2
WHERE t2.name = t1.name
ORDER BY t2.active DESC, t2.created DESC, t2.prid DESC
LIMIT 1
)
ORDER BY t1.active DESC, t1.created DESC, t1.prid DESC
LIMIT 50
,有什么想法吗?
@Rick James
SQL Fiddle链接:http://sqlfiddle.com/#!9/f9b39/2/0
答案 0 :(得分:0)
使用ANSI标准的row_number()
函数:
select t.*
from (select t.*,
row_number() over (partition by name
order by active desc, created desc, pid desc
) as seqnum
from source_table t
) t
where seqnum = 1;
以上内容适用于MySQL 8+和MariaDB 10.2+。在早期版本中,您可以执行以下操作:
select t.*
from source_table t
where t.prid = (select t2.prid
from source_table t2
where t2.name = t.name
order by t2.active desc, t2.created desc, t2.pid desc
limit 1
);
为了提高性能,您希望在source_table(name, actdive desc, created desc, pid desc, prid)
上建立索引。
答案 1 :(得分:0)
ORDER BY IFNULL(active, -1) DESC,
IFNULL(created, -1) DESC,
IFNULL(pid, -1) DESC,
完整提示
SELECT prid, name, active, created
FROM
( SELECT GROUP_CONCAT(prid
ORDER BY IFNULL(active, -1) DESC,
IFNULL(created, -1) DESC,
IFNULL(prid, -1) DESC
) AS ids
FROM source_table
GROUP BY name
) AS s1
JOIN source_table AS s2
ON s2.prid = SUBSTRING_INDEX(s1.ids, ',', 1)
ORDER BY IFNULL(active, -1) DESC,
IFNULL(created, -1) DESC,
IFNULL(prid, -1) DESC ;