SQL DELETE FROM LEFT JOIN SELECT

时间:2016-11-02 00:46:18

标签: sql sql-server select join sql-delete

我在SQL Server 2012中有这个查询

DELETE FROM [DB1].[dbo].[Newsletter] 
WHERE [DB1].[dbo].[Newsletter].RecordID IN
            (SELECT TOP(100) *
             FROM [DB1].[dbo].[Newsletter] 
             LEFT JOIN [DB1].[dbo].[Newsletter_Tracking] ON RecordId = Newsletter_Tracking.UserId
             WHERE Newsletter.DateSubscribed < '2010-01-01')

没有删除的选择正常。它返回所有不在左表中且比2010年早的行。

我收到了这个错误:

  

Msg 116,Level 16,State 1,Line
  当未使用EXISTS引入子查询时,只能在选择列表中指定一个表达式。

3 个答案:

答案 0 :(得分:2)

当您使用IN运算符时,子查询必须返回一个列/值,这意味着您无法使用select *

在你的情况下,它很可能是:

DELETE FROM [DB1].[dbo].[Newsletter] 
WHERE [DB1].[dbo].[Newsletter].RecordID IN (
  SELECT [DB1].[dbo].[Newsletter].RecordID
  FROM [DB1].[dbo].[Newsletter] 
  LEFT JOIN [DB1].[dbo].[Newsletter_Tracking] ON RecordId = Newsletter_Tracking.UserId
  WHERE Newsletter.DateSubscribed<'2010-01-01'
)

此外,使用top没有任何order by子句会给您一个随机结果 - top应始终与order by子句一起使用。

答案 1 :(得分:2)

嗯,RecordId中需要SELECTIN列表仅识别单例值,因此SELECT *通常不起作用。

DELETE FROM [DB1].[dbo].[Newsletter] 
WHERE [DB1].[dbo].[Newsletter].RecordID IN
(SELECT TOP(100) RecordId
  FROM [DB1].[dbo].[Newsletter] LEFT JOIN [DB1].[dbo].[Newsletter_Tracking]
  ON RecordId=Newsletter_Tracking.UserId
  WHERE Newsletter.DateSubscribed<'2010-01-01')

您的查询不会执行此操作:

  

没有删除的选择正常。它返回所有的行   不在左表中且比2010年旧。

但我怀疑你想要更像这样的东西:

DELETE n
    FROM [DB1].[dbo].Newsletter n
    WHERE n.DateSubscribed < '2010-01-01' AND
          n.RecordID NOT IN (SELECT nt.UserId
                             FROM [dbo].[Newsletter_Tracking] nt
                            );

我不确定TOP 100的位置。您的问题没有提及。

答案 2 :(得分:1)

您也可以使用不存在条款,

DELETE n
    FROM [DB1].[dbo].Newsletter n
    WHERE n.DateSubscribed < '2010-01-01' AND
         NOT EXISTS (SELECT nt.UserId
                             FROM [dbo].[Newsletter_Tracking] nt.UserId= n.RecordID
                            );