【问题标题】:How to convert 'not in' statement to join with group by如何将“不在”语句转换为加入 group by
【发布时间】:2014-11-06 05:08:35
【问题描述】:

如何获取所有记录,除了按record_id分组的最新记录?

表:

attachments
+-----------+------------------+------+-----+---------+----------------+
| Field     | Type             | Null | Key | Default | Extra          |
+-----------+------------------+------+-----+---------+----------------+
| id        | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| record_id | int(11)          | NO   |     | NULL    |                |
| created   | date             | NO   |     | NULL    |                |
+-----------+------------------+------+-----+---------+----------------+

表格附件中的源测试行:

mysql> select * from attachments;
+----+-----------+------------+
| id | record_id | created    |
+----+-----------+------------+
|  1 |         1 | 2014-11-05 |
|  2 |         1 | 2014-11-04 |
|  3 |         1 | 2014-11-03 |
|  4 |         1 | 2014-11-02 |
|  5 |         2 | 2014-11-05 |
|  6 |         2 | 2014-11-04 |
|  7 |         2 | 2014-11-03 |
+----+-----------+------------+

我创建了这个查询,但是对于大表来说太慢了:

SELECT * FROM attachments WHERE id NOT IN (
SELECT 
attachments.id
FROM attachments
GROUP BY attachments.record_id
ORDER BY attachments.`created` DESC
)

结果:

+----+-----------+------------+
| id | record_id | created    |
+----+-----------+------------+
|  2 |         1 | 2014-11-04 |
|  3 |         1 | 2014-11-03 |
|  4 |         1 | 2014-11-02 |
|  6 |         2 | 2014-11-04 |
|  7 |         2 | 2014-11-03 |
+----+-----------+------------+

我的加入查询得到相反的结果,选择的唯一最新的按record_id分组:

SELECT  old.*
FROM attachments `old`
INNER JOIN attachments `new` ON `new`.id = `old`.id
GROUP BY new.record_id
ORDER BY old.`created` DESC

结果:

+----+-----------+------------+
| id | record_id | created    |
+----+-----------+------------+
|  1 |         1 | 2014-11-05 |
|  5 |         2 | 2014-11-05 |
+----+-----------+------------+

将 INNER 更改为 RIGHT 或 LEFT 不会更改输出结果。

【问题讨论】:

    标签: mysql sql join group-by


    【解决方案1】:

    试试这个查询:

    SELECT t1.* FROM attachments t1 
    left outer join
    (SELECT attachments.id
    FROM attachments
    GROUP BY attachments.record_id
    ORDER BY attachments.`created` DESC) t2 on t1.id = t2.id
    where t2.id is null;
    

    SQL Fiddle

    【讨论】:

    • 这个查询比我的第一个查询慢。
    • 你在表中使用了索引吗?
    【解决方案2】:
    Select *
    From attachments a
    Where exists (Select *
                  From attachments a2
                  Where a.record_id = a2.record_id
                  and   a.created < a2.created);
    

    此查询检查以确保存在具有相同记录 ID 和较新创建日期的其他数据。如果您有两个具有相同 record_id 和创建日期的 id 作为最近的两条记录,这将不起作用。此查询将忽略它们。

    【讨论】:

      猜你喜欢
      • 2012-07-29
      • 2016-01-21
      • 2014-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多