SQL Server - 在WHERE子句中使用谓词的替代方法

时间:2018-04-04 19:33:36

标签: sql sql-server-2012

我想删除我的DemoTable中的所有事件,其中第一个事件和该交互的最后一个事件之间的差异大于30分钟。我编写了一个select语句来查看所有这些事件,并使用HAVING关键字来获取DATEDIFF大于30分钟的事件。

由于我无法在删除中使用HAVING或在WHERE子句中使用谓词,因此在下面的错误代码中执行我想要做的事情的最佳替代/正确方法是什么...

DELETE
FROM dbo.DemoTable dt
WHERE DATEDIFF(MINUTE, MIN(dt.utc), MAX(dt.utc)) > 30
GROUP BY dt.interactionId;
GO

编辑:感谢大家的建议!

5 个答案:

答案 0 :(得分:4)

快速而肮脏的方式是这样的:

DELETE FROM
    dbo.DemoTable
WHERE
    dto.DemoTable.YourPrimaryKey IN
    (
        SELECT
            YourPrimaryKey
        FROM
            -- your query here
    )

这仅适用于非复合主键。

答案 1 :(得分:1)

我认为其中一种方法是使用包含有效数据的temptable并使用这些数据来消除无效的数据,如下所示:

SELECT dt.interactionid
INTO #temp
FROM DemoTable dt
WHERE DATEDIFF(MINUTE, MIN(dt.utc), MAX(dt.utc)) <= 30

DELETE dt
FROM DemoTable dt
WHERE NOT EXISTS (select * from #temp t where t.interactionid = dt.interactionid)

答案 2 :(得分:1)

子查询?

delete from dbo.demotable
where interactionid in 
    (select dt.interactionid
    from dbo.demotable dt
    WHERE DATEDIFF(MINUTE, MIN(dt.utc), MAX(dt.utc)) > 30
    GROUP BY dt.interactionId)

取决于sql的版本,你可以像这样删除它:

delete from dt
from dbo.demotable dt
WHERE DATEDIFF(MINUTE, MIN(dt.utc), MAX(dt.utc)) > 30

答案 3 :(得分:1)

如果要删除所有此类交互,可以使用连接或可更新CTE。我会选择后者:

with todelete as (
      select dt.*, 
             min(dt.utc) over (partition by dt.interactionId) as min_utc,
             max(dt.utc) over (partition by dt.interactionId) as max_utc
      from dbo.DemoTable dt
     )
delete from todelete
    where datediff(day, min_utc, max_utc) > 30;

答案 4 :(得分:1)

您可以使用子查询

DELETE FROM dbo.DemoTable dt
WHERE id IN (
    SELECT id FROM dbo.DemoTable
    -- The rest of your query
)
GO