在IF EXISTS查询中使用CTE


8

是否可以在SQL Server 2012中执行与以下类似的操作?

IF EXISTS (
    WITH DATA AS (
        SELECT *, 
        ROW_NUMBER() OVER(PARTITION BY column ORDER BY Column) AS rn
        FROM table )
    SELECT *
    FROM DATA
    WHERE rn = 2 )
BEGIN
...
END

我尝试使用此语法并收到错误。如果无法做到这一点,使用临时表是否是实现此目的的最佳方法?


BOL-创建和使用公用表表达式的准则中,您无法做到。最好是使用临时表
Kin Shah

为什么不IF EXISTS (SELECT * FROM table)呢?
ypercubeᵀᴹ

@ypercube我提供的示例不是我正在使用的查询的精确副本-查看表是否包含行对于我尝试的操作是不够的。我想这样说可能更准确WHERE rn = 2
Weston Sankey

1
然后您也可以说IF EXISTS (SELECT column FROM dbo.table GROUP BY column HAVING COUNT(*)>1)
亚伦·伯特兰

Answers:


10

CTE不能用作子查询。一种解决方法是:

IF EXISTS 
(
  SELECT 1 FROM 
  (
    SELECT ROW_NUMBER() OVER(PARTITION BY column ORDER BY Column) AS rn
    FROM table
  ) AS DATA 
  WHERE rn = 2
)
BEGIN
  ...
END

另一个可能是:

IF EXISTS (SELECT 1 FROM dbo.table GROUP BY column HAVING COUNT(*) > 1)
BEGIN
  ...
END

即使你提出的语法是有效的,该EXISTS会在这种情况下,不短路,无论如何,我认为(我怀疑这就是为什么你会想使用它),因为之前的窗口函数必须兑现了全套rn能被过滤。


4

另一种选择是使用变量:

DECLARE @HasRows bit = 0;

WITH foo as 
(
    ...
)
SELECT TOP(1) @HasRows = 1
FROM foo;

IF @HasRows
BEGIN
    PRINT 'True';
END

2

我认为您可以使用如下代码:

IF OBJECT_ID('tempdb..#data1') IS NOT NULL
            BEGIN 
                DROP TABLE #data1;
            END;

           CREATE TABLE #data1 (
id INT
)

IF OBJECT_ID('tempdb..#data2') IS NOT NULL
                BEGIN 
                    DROP TABLE #data2;
                END;

CREATE TABLE #data2 (
id INT
)

INSERT INTO #data1
VALUES (1), (2), (3), (4)

INSERT INTO #data2
VALUES (4), (5)

DECLARE @result INT = 0;


;WITH result_set AS (
SELECT id FROM #data1
  UNION 
SELECT id FROM #data2
)
SELECT @result = 1 FROM result_set WHERE id = 5 --6

IF (@result = 1)
BEGIN 
SELECT 'YAHOO'
END 

条件结果可以存储为变量。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.