2017-07-20 25 views
0

我的數據是這樣的:查找列

+--------------+------------+----------+ 
| name | id | data | date | 
+-------+------+-----------------------+ 
| host1 | 1 | data1 |07/20/2017| 
| host1 | 1 | data2 |07/20/2017| 
| host2 | 2 | data1 |07/20/2017| 
| host2 | 3 | data1 |07/19/2017| 
| host3 | 4 | data1 |07/20/2017| 
| host3 | 4 | data2 |07/20/2017| 
| host3 | 4 | data3 |07/20/2017| 
| host3 | 4 | data4 |07/20/2017| 
| host4 | 5 | data3 |07/20/2017| 
| host4 | 6 | data4 |07/17/2017| 
+-------+------+------------+----------+ 

我需要能夠從表中刪除了一些過時的數據。數據對於每個對象都有多行。但是我需要能夠搜索表格並找到「名稱」匹配但「ID」不匹配的實例。然後刪除較舊的記錄。在上面的數據示例中,我想delete from tableName where ID = '3' or '6'

我已經能夠使用以下查詢來隔離哪些不匹配,但我無法弄清楚如何逐步通過每一個(特別是如果有是需要刪除的多個「名稱」)。

SELECT * 
FROM tableName 
WHERE NAME IN (SELECT T1.NAME 
        FROM aid2245.tableName T1 
          INNER JOIN aid2245.tableName T2 
            ON T1.NAME = T2.NAME 
        WHERE T1.ID <> T2.ID) 

任何幫助,將不勝感激。

謝謝!

回答

1

這將刪除3和6

create table tableName 
    (id int, 
    name varchar(50), 
    [date] date) 

    GO 

-- Sample data 

    insert into tableName 
    (name, id, [date]) 
    values('host1' , 1 , '07/20/2017'), 
    ('host1' , 1 , '07/20/2017'), 
    ( 'host2' , 2 , '07/20/2017'), 
    ('host2' , 3 , '07/19/2017'), 
    ('host3' , 4 , '07/20/2017'), 
    ( 'host3' , 4 , '07/20/2017'), 
    ( 'host3' , 4 , '07/20/2017'), 
    ( 'host3' , 4 , '07/20/2017'), 
    ( 'host4' , 5 , '07/20/2017'), 
    ( 'host4' , 6 , '07/17/2017') 

    GO 

-- Look at what we are deleting first. 

    SELECT b.* 
    FROM (SELECT name, max(date) maxDate 
      FROM tableName 
      GROUP BY name) AS a 
    JOIN tableName AS b 
    ON a.name = b.name 
    AND b.date < a.maxDate 
    AND b.Id not in 
    (SELECT max(id) 
     FROM tableName 
     GROUP BY [date] 
     HAVING date = maxDate) 

    GO 

-- delete the older rows 

    DELETE b 
    FROM (SELECT name, max(date) maxDate 
      FROM tableName 
      GROUP BY name) AS a 
    JOIN tableName AS b 
    ON a.name = b.name 
    AND b.date < a.maxDate 
    AND b.Id not in 
     (SELECT max(id) 
     FROM tableName 
     GROUP BY [date] 
     HAVING date = maxDate) 

    GO 
0

以下應該做的伎倆。

IF OBJECT_ID('tempdb..#TestData', 'U') IS NULL 
BEGIN -- DROP TABLE #TestData 
    CREATE TABLE #TestData (
     [name] CHAR(5) NOT NULL, 
     id INT NOT NULL, 
     [data] CHAR(5) NOT NULL, 
     [date] DATE NOT NULL 
     ); 

    INSERT #TestData (name, id, data, date) VALUES 
     ('host1', 1, 'data1', '07/20/2017'), 
     ('host1', 1, 'data2', '07/20/2017'), 
     ('host2', 2, 'data1', '07/20/2017'), 
     ('host2', 3, 'data1', '07/19/2017'), 
     ('host3', 4, 'data1', '07/20/2017'), 
     ('host3', 4, 'data2', '07/20/2017'), 
     ('host3', 4, 'data3', '07/20/2017'), 
     ('host3', 4, 'data4', '07/20/2017'), 
     ('host4', 5, 'data3', '07/20/2017'), 
     ('host4', 6, 'data4', '07/17/2017'); 
END; 

--========================================================== 

-- 1) View before DELETE... 
SELECT 
    *, 
    NeedsDelete = CASE WHEN td.id = LAG(td.id, 1, td.id) OVER (PARTITION BY td.name ORDER BY td.date) THEN '' ELSE 'Delete' END 
FROM 
    #TestData td 
ORDER BY 
    td.name, 
    td.date DESC; 

-- 2) Do the actual DELETE... 
WITH 
    cte_FindDelete AS (
     SELECT 
      *, 
      NeedsDelete = CASE WHEN td.id = LAG(td.id, 1, td.id) OVER (PARTITION BY td.name ORDER BY td.date) THEN '' ELSE 'Delete' END 
     FROM 
      #TestData td 
     ) 
DELETE fd 
FROM 
    cte_FindDelete fd 
WHERE 
    fd.NeedsDelete = 'Delete'; 

HTH, 傑森

0

我會窗口功能做到這一點:

with todelete as (
     select t.*, 
      min(id) over (partition by name) as minid, 
      max(id) over (partition by name) as maxid, 
      row_number() over (partition by name order by date desc) as seqnum 
     from tablename t 
    ) 
delete from todelete 
    where minid <> maxid and seqnum > 1;