0

希望每组返回一行,其中一行由多个排序列选择。的土地上小心行事,以避免重复的问题。

架构:

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=1id. 此查询当前首先为每个返回正确的行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

今天我的解决方法是在 PHP 中使用if ($lastIP == $row['ip_address']) continue;. 但我想将此逻辑移至 MySQL。

4

4 回答 4

1

尝试这个 -

SELECT MIN(id), ip_address, status
FROM logs
GROUP BY ip_address, status
于 2017-12-04T15:48:09.303 回答
0

由于在 MySQL 中已经有数百种针对每组最大 n 问题的解决方案,我将开始使用带有窗口函数的 CTE 语法来回答这些问题,因为现在 MySQL 8.0.3 中提供了这些问题。

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;
于 2017-12-04T15:58:15.760 回答
0

Here is different way to think about the problem. You want to find the "best" row for each id_address. Or in other words, you want to select rows where no better row exists.

This solution works for MySQL versions before 8.0. In other words, it works with the version you already have installed with RHEL 7. You can extend this technique easily for an arbitrary number of sort columns.

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

If you have more columns to sort by then keeping adding OR clauses to handle tie breaks and select the "best" row for each ip_address. Regardless how complicated your subquery is or how many "SORT BY~ conditions you have, you will only need one LEFT JOIN with this technique.

于 2018-06-27T14:43:08.420 回答
-2

尝试这个:

SELECT 
l.`ip_address` , l.`status`
FROM
  `logs` l 
GROUP BY l.`ip_address` 
ORDER BY l.`status` = 1 DESC
于 2017-12-04T16:29:23.543 回答