簡體   English   中英

最近30天未出現來自同一表的查詢記錄

[英]Query records from same table not present in last 30 days

我有一個名為頁面加載的表,其后各列

user_id
timestamp
country
city

該表有3,700萬條記錄,兩列均具有索引

時間戳記范圍從7/23到9/27

我需要做的是:對於日期范圍8/24到9/27,每天計算表中前30天不存在的不同用戶。

因此,對於表中存在於8/24的用戶,查找表7/23與8/23之間不存在的不同用戶的數量。 在8/24至9/27之間的每一天都需要執行相同的操作。

select
    count(distinct user_id)
from
    pageloads
where
    user_id not in (select user_id from pageloads where time between
'2015-07-24 00:00:00' and '2015-08-23 23:59:59')
and left(time,10) = '2015-08-24'

由於沒有in子句,因此這種方法非常慢,並且一次只能運行1天。

有人能幫助我嗎。

嘗試使用

AND NOT EXIST ( select 1 from pageloads p1 where  p1.time between
'2015-07-24 00:00:00' and '2015-08-23 23:59:59' and p1.user_id = user_id)

NOT EXIST非常有效,因為當找到1條記錄時它將停止搜索。 如果沒有記錄,則將立即發現它。 也可以使用user_id上的索引。

如果您有子查詢,則IN子句非常慢。更好地使用臨時表和聯接,它要快得多。

我進行了一些測試,找到了最佳解決方案。 我現在沒有多久生成一次此報告,但是如果您使用新的累積表,我將獲得最佳結果。

在此表中,您存儲每天/用戶的累積值,如果要在第二天生成報告,則僅用一天中的數據更新新表是唯一必要的。

新表

CREATE TABLE `pageload_cum` (
  `user_id` INT(11) NOT NULL DEFAULT '0',
  `time` DATE,
  `quantity` INT(11) DEFAULT NULL,
  PRIMARY KEY (`user_id`,`time`),
  KEY `time` (`time`,`user_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

填表

該查詢將插入最近60天的所有數據,這些數據將用於昨天開始的報告。 如果明天開始,只會產生缺少的一天

INSERT IGNORE INTO pageload_cum
SELECT DISTINCT p.user_id ,
  DATE(p.`time`),
  SUM(1) AS quantity 
FROM pageloads p
WHERE
 DATE(p.`time`) NOT IN (
   SELECT DISTINCT p.time FROM pageload_cum p
 )
AND p.`time` > SUBDATE(NOW(), INTERVAL 61 DAY)
AND p.`time` < SUBDATE(NOW(), INTERVAL 1 DAY)
GROUP BY DATE(p.`time`), p.user_id;

現在的報告

該報告生成一些僅用於了解結果的列。 如果不使用它們,則可以刪除它們。 對於一列“ group_concat_max_len”,必須將一個變量設置為可以容納完整結果的大小。 您可以在查詢之前進行設置,也可以直接在my.cnf中進行設置。

SET  group_concat_max_len=16384;

SELECT
  DATE(p.`time`) checkdate,
  DATE(SUBDATE(`p`.`TIME`, INTERVAL 31 DAY)) AS hist_start,
  DATE(SUBDATE(`p`.`TIME`, INTERVAL 1 DAY)) AS hist_end,
   sum(1) AS cnt_user,
  GROUP_CONCAT(DISTINCT p.user_id SEPARATOR ', ') user_not_hist
  FROM pageload_cum  p
  LEFT JOIN pageload_cum hist
    ON  `hist`.`TIME` BETWEEN DATE(SUBDATE(`p`.`TIME`, INTERVAL 31 DAY)) AND DATE(SUBDATE(`p`.`TIME`, INTERVAL 1 DAY))
    AND p.user_id = hist.user_id
  WHERE 
  hist.user_id IS NULL
 AND
   `p`.`TIME`  BETWEEN '2015-09-01 00:00:00' AND '2015-09-30 23:59:59' 
   GROUP BY DATE(`p`.`TIME`);

結果

我僅在頁面加載表中使用10.000.000行測試了此查詢,並為此結果更改了一些數據。

+------------+------------+------------+----------+--------------------------+
| checkdate  | hist_start | hist_end   | cnt_user | user_not_hist            |
+------------+------------+------------+----------+--------------------------+
| 2015-09-13 | 2015-08-13 | 2015-09-12 |        1 | 3333                     |
| 2015-09-27 | 2015-08-27 | 2015-09-26 |        4 | 4567, 5678, 12345, 31313 |
+------------+------------+------------+----------+--------------------------+
2 rows in set (0.29 sec)

至少

不必刪除孔表。 您只能從不再使用的日期中刪除舊數據,例如

DELETE FROM pageload_cum WHERE `time` < DATE(SUBDATE(now(), INTERVAL 100 DAY));

如果您想要該報告,請立即讓我。

暫無
暫無

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

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