簡體   English   中英

SQL查詢以選擇具有最大列值的所有行

[英]SQL query to select all rows with max column value

CREATE TABLE `user_activity` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `type` enum('request','response') DEFAULT NULL,
  `data` longtext NOT NULL,
  `created_at` datetime DEFAULT NULL,
  `source` varchar(255) DEFAULT NULL,
  `task_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

我有這些數據:

在此處輸入圖片說明

現在,我需要為user_id=527選擇所有行,其中created_at值是最大值。 所以我需要這張圖片的最后3行。

我寫了這個查詢:

SELECT * 
FROM   user_activity 
WHERE  user_id = 527 
       AND source = 'E1' 
       AND task_name IN ( 'GetReportTask', 'StopMonitoringUserTask' ) 
       AND created_at = (SELECT Max(created_at) 
                         FROM   user_activity 
                         WHERE  user_id = 527 
                                AND source = 'E1' 
                                AND task_name IN ( 'GetReportTask', 
                                                   'StopMonitoringUserTask' ));

這是非常低效的,因為我再次運行與內部查詢完全相同的查詢,只是它忽略了created_at 什么是正確的方法?

按created_at desc排序,並將查詢限制為返回1行。

SELECT * 
FROM   user_activity 
WHERE  user_id = 527 
   AND source = 'E1' 
   AND task_name IN ( 'GetReportTask', 'StopMonitoringUserTask' ) 
ORDER BY created_at DESC
LIMIT 1;

我將使用相關的子查詢:

SELECT ua.* 
FROM user_activity ua
WHERE ua.user_id = 527 AND source = 'E1' AND
      ua.task_name IN ('GetReportTask', 'StopMonitoringUserTask' ) AND
      ua.created_at = (SELECT MAX(ua2.created_at) 
                       FROM user_activity ua2
                       WHERE ua2.user_id = ua.user_id AND 
                             ua2.source = ua.source AND
                             ua2.task_name IN ( 'GetReportTask', 'StopMonitoringUserTask' )
                      );

盡管這似乎效率低下,但是您可以在user_activity(user_id, source, task_name, created_at)上創建索引。 使用此索引,查詢應具有良好的性能。

我使用EverSQL並進行了自己的更改,以提出使用自連接的單選查詢:

SELECT * 
FROM   user_activity AS ua1 
       LEFT JOIN user_activity AS ua2 
              ON ua2.user_id = ua1.user_id 
                 AND ua2.source = ua1.source 
                 AND ua2.task_name IN ( 'GetReportTask', 'StopMonitoringUserTask' ) 
                 AND ua1.created_at < ua2.created_at 
WHERE  ua1.user_id = 527 
       AND ua1.source = 'E1' 
       AND ua1.task_name IN ( 'GetReportTask', 'StopMonitoringUserTask' ) 
       AND ua2.created_at IS NULL;

但是,我注意到兩個查詢的響應時間都差不多。 我試圖使用Explain來識別性能差異。 從我的輸出中了解,由於適當的索引已建立,因此沒有明顯的差異。 因此,為了提高可讀性和可維護性,我將僅使用嵌套查詢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM