简体   繁体   English

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

[英]SQL Server - Alternative To Using a Predicate In a WHERE Clause

I would like to delete all of the events in my DemoTable where the difference between the first event and last event for that interaction is greater than 30 minutes. 我想删除我的DemoTable中的所有事件,其中第一个事件和该交互的最后一个事件之间的差异大于30分钟。 I wrote a select statement to look at all of these events and used the HAVING keyword to get the events that have a DATEDIFF of greater than 30 minutes. 我编写了一个select语句来查看所有这些事件,并使用HAVING关键字来获取DATEDIFF大于30分钟的事件。

Since I can't use a HAVING in a delete or use a predicate in a WHERE clause, what is the best alternative/proper way to do what I want to do in the incorrect code below... 由于我不能在删除中使用HAVING或在WHERE子句中使用谓词,因此在下面的错误代码中执行我想要做的事情的最佳替代/正确方法是什么...

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

EDIT: Thank you to everyone for their suggestions! 编辑:谢谢大家的建议!

A quick and dirty way is like this: 快速而肮脏的方式是这样的:

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

This only works for non-composite primary-keys. 这仅适用于非复合主键。

I think one of the alternative is to use a temptable containing the valid data and use those data to eliminate invalid ones like below: 我认为其中一种方法是使用包含有效数据的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)

A sub query? 一个子查询?

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)

depending on the version of sql you could just delete it like so: 根据sql的版本你可以删除它,如下所示:

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

If you want to remove all such interactions, you can use a join or an updatable CTE. 如果要删除所有此类交互,可以使用连接或可更新的CTE。 I would go for the latter: 我会选择后者:

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;

You can use subqueries 您可以使用子查询

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM