[英]SQL - One row for each name
尝试利用https://stackoverflow.com/a/123481中的技术我试图为每个name
检索一行,具有特定的排序,即按active
created
后的降序排序后的第一行/第一行,然后prid
。 但是, active
列可能包含numberic或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 |
+------+-------+--------+---------+
期望的结果:
+------+-------+--------+---------+
| prid | name | active | created |
+------+-------+--------+---------+
| 9 | egg | 4 | 4 |
| 4 | bat | 3 | 0 |
| 5 | noise | NULL | 2 |
| 8 | cup | NULL | 0 |
+------+-------+--------+---------+
SQL:
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
实际结果:
+------+-------+--------+---------+
| prid | name | active | created |
+------+-------+--------+---------+
| 9 | egg | 4 | 4 |
| 4 | bat | 3 | 0 |
| 1 | bat | NULL | 3 |
| 5 | noise | NULL | 2 |
| 8 | cup | NULL | 0 |
+------+-------+--------+---------+
@Gordon Linoff
感谢您的帮助,我尝试使用第二个版本的索引(name, active, created, prid)
和(active, created, prid)
,但它很慢。
这需要1秒钟,返回正确的结果,但顺序错误:
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
这需要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
)
ORDER BY t1.active DESC, t1.created DESC, t1.prid DESC
LIMIT 50
我真的需要LIMIT 500
,任何想法?
@Rick James
SQL小提琴链接: http ://sqlfiddle.com/#!9 / f9b39 / 2/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)
上的索引source_table(name, actdive desc, created desc, pid desc, prid)
。
ORDER BY IFNULL(active, -1) DESC,
IFNULL(created, -1) DESC,
IFNULL(pid, -1) DESC,
完整的Stmt
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 ;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.