希望每组返回一行,其中一行由多个排序列选择。在greatest-n-per-group的土地上轻轻踩踏以避免重复的问题。
SCHEMA:
CREATE TABLE logs (
id INT NOT NULL,
ip_address INT NOT NULL,
status INT NOT NULL,
PRIMARY KEY id
);
数据:
INSERT INTO logs (id, ip_address, status)
VALUES ('1', 19216800, 1),
('2', 19216801, 2),
('3', 19216800, 2),
('4', 19216803, 0),
('5', 19216804, 0),
('6', 19216803, 0),
('7', 19216804, 1);
当前查询:
SELECT *
FROM logs
ORDER BY ip_address, status=1 DESC, id DESC
注意:按status=1
排序有效地将状态列转换为布尔值。 status=1
之后的平局建立者是id
。此查询当前首先返回每个ip_address
的正确行,然后返回我不想要ip_address
的其他行。
当前输出:
1, 19216800, 1
3, 19216800, 2
2, 19216801, 2
6, 19216803, 0
4, 19216803, 0
7, 19216804, 1
5, 19216804, 0
通缉输出:
1, 19216800, 1
2, 19216801, 2
6, 19216803, 0
7, 19216804, 1
今天我的解决方法是使用if ($lastIP == $row['ip_address']) continue;
在PHP中进行过滤。但我想把这个逻辑移到MySQL上。
答案 0 :(得分:1)
试试这个 -
SELECT MIN(id), ip_address, status
FROM logs
GROUP BY ip_address, status
答案 1 :(得分:0)
由于MySQL已经有数百种针对每组最大问题的解决方案,我将开始用带窗函数的CTE语法回答这些问题,因为现在可以在MySQL 8.0.3中使用。 / p>
WITH sorted AS (
SELECT id, ip_address, status,
ROW_NUMBER() OVER (PARTITION BY ip_address ORDER BY status) AS rn
FROM logs
)
SELECT * FROM sorted WHERE rn = 1;
答案 2 :(得分:0)
这里是思考问题的另一种方式。您想为每个id_address
找到“最佳”行。换句话说,您想选择没有更好行的行。
此解决方案适用于8.0之前的MySQL版本。换句话说,它可以与已经在RHEL 7中安装的版本一起使用。您可以轻松地将此技术扩展到任意数量的排序列。
SELECT a.*
FROM (SELECT * FROM logs) a
LEFT JOIN (SELECT * FROM logs) b
ON (b.ip_address = a.ip_address AND (b.stat=1) > (a.stat=1))
OR (b.ip_address = a.ip_address AND (b.stat=1) = (a.stat=1) AND b.id > a.id)
WHERE b.id IS NULL
ORDER BY a.ip_address
如果要排序的列更多,则继续添加OR
子句来处理平局,并为每个ip_address
选择“最佳”行。不管您的子查询多么复杂,或者您有多少个“ SORT BY
〜”条件,使用这种技术都只需要一个LEFT JOIN
。
答案 3 :(得分:-2)
试试这个:
public class NavigationModel
{
public List<NavigationNode> NavigationNodes { get; set; }
public NavigationModel()
{
}
private class NavigationNode
{
}
}