簡體   English   中英

SQL-僅保留每天的第一條記錄和最后一條記錄

[英]SQL - Keep only the first and last record of each day

我有一個存儲簡單日志數據的表:

CREATE TABLE chronicle (
    id INT auto_increment PRIMARY KEY, 
    data1 VARCHAR(256),
    data2 VARCHAR(256),
    time DATETIME
);

該表正在接近100萬條記錄,因此我想開始合並數據。

我希望能夠每天獲取每個DISTINCT(data1, data2)的第一條記錄和最后一條記錄,並刪除所有其余記錄。

我知道如何只提取數據並以我想要的任何語言處理它,然后使用巨大的IN (...)查詢刪除記錄,但是似乎更好的選擇是直接使用SQL(我錯了嗎?)

我已經嘗試了幾個查詢,但是除了JOIN之外,我對SQL並不滿意。

這是我到目前為止的內容:

SELECT id, Max(time), Min(time)
FROM   (SELECT id, data1 ,data2, time, Cast(time AS DATE) AS day
        FROM chronicle) AS initial
GROUP BY day;

這使我獲得了每天的第一時間和最后一次時間,但並沒有被數據分開(即,我得到了每天的最后一條記錄,而不是每天每一組不同數據的最后一條記錄。)此外, id僅用於最小(時間)。

我在此特定問題上發現的信息僅用於查找當天的最后一條記錄,而不是查找數據集的每條最后一條記錄。

重要提示:我想要每天每個DISTINCT(data1, data2)的第一條/最后一條記錄,而不僅僅是表中每一天的第一條/最后一條記錄。 每天將有2條以上的記錄。

解決方案:感謝Jonathan Dahan和Gordon Linoff的解決方案:

SELECT o.data1, o.data2, o.time FROM chronicle AS o JOIN (
    SELECT Min(id) as id FROM chronicle GROUP BY DATE(time), data1, data2
    UNION SELECT Max(id) as id FROM test_chronicle GROUP BY DATE(time), data1. data2
) AS n ON o.id = n.id;

從這里開始,只需引用同一張表即可刪除行。

你有正確的主意。 您只需要重新加入即可獲取原始信息。

SELECT c.*
FROM chronicle c JOIN
     (SELECT date(time) as day, min(time) as mint, max(time) as maxt
      FROM chronicle
      GROUP BY date(time)
     ) cc
     ON c.time IN (cc.mint, cc.maxt);

請注意, join條件不需要明確地包括day因為它是time一部分。 當然,您可以根據需要添加date(c.time) = cc.day

建議您創建一個新表,而不是刪除原始表中的行。 謊言是這樣的:

create table ChronicleByDay like chronicle;

insert into ChronicleByDay
    SELECT c.*
    FROM chronicle c JOIN
         (SELECT date(time) as day, min(time) as mint, max(time) as maxt
          FROM chronicle
          GROUP BY date(time)
         ) cc
         ON c.time IN (cc.mint, cc.maxt);

這樣,如果需要,您可以獲取更詳細的信息。

搜索日期時,這將提高性能。

ALTER TABLE chronicle
ADD INDEX `ix_chronicle_time` (`time` ASC);

這將刪除記錄:

CREATE TEMPORARY TABLE #tmp_ids (
  `id` INT NOT NULL,
  PRIMARY KEY (`id`)
);

INSERT INTO #tmp_ids (id)
SELECT
    min(id)
FROM
    chronicle
GROUP BY
    CAST(day as DATE),
    data1,
    data2
UNION
SELECT
    Max(id)
FROM
    chronicle
GROUP BY
    CAST(day as DATE),
    data1,
    data2;

DELETE FROM
    chronicle
WHERE
    ID not in (select id FROM #tmp_ids)
    AND date <= '2015-01-01'; -- if you want to consider all dates, then remove this condition

暫無
暫無

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

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