Verwenden eines CTE in IF EXISTS Query

8

Ist es möglich, in SQL Server 2012 etwas Ähnliches wie das Folgende zu tun?

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

Ich habe versucht, diese Syntax zu verwenden, und eine Fehlermeldung erhalten. Wenn dies nicht möglich ist, wäre die Verwendung einer temporären Tabelle der beste Weg, um dies zu erreichen?

Weston Sankey
quelle
In BOL - Richtlinien zum Erstellen und Verwenden allgemeiner Tabellenausdrücke können Sie nicht. Am besten verwenden Sie eine temporäre Tabelle .
Kin Shah
Warum nicht IF EXISTS (SELECT * FROM table)?
Ypercubeᵀᴹ
@ypercube Das Beispiel, das ich bereitgestellt habe, ist keine exakte Nachbildung der Abfrage, mit der ich arbeite. Wenn die Tabellen Zeilen enthalten, würde dies bei dem, was ich versuche, nicht ausreichen. Ich denke, es wäre genauer gewesen zu sagenWHERE rn = 2
Weston Sankey
1
Dann könnte man auch sagenIF EXISTS (SELECT column FROM dbo.table GROUP BY column HAVING COUNT(*)>1)
Aaron Bertrand

Antworten:

10

Ein CTE kann nicht als Unterabfrage verwendet werden. Eine Problemumgehung wäre:

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

Ein anderer wäre:

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

Selbst wenn Ihre vorgeschlagene Syntax gültig wäre, EXISTSwürde das in diesem Fall ohnehin nicht kurzschließen, würde ich denken (und ich vermute, dass Sie sie deshalb verwenden möchten), da die Fensterfunktion über den gesamten Satz hinweg materialisieren muss, bevor rndies möglich ist gefiltert werden.

Aaron Bertrand
quelle
4

Eine andere Option ist die Verwendung einer Variablen:

DECLARE @HasRows bit = 0;

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

IF @HasRows
BEGIN
    PRINT 'True';
END
Mitch
quelle
2

Ich denke, Sie können Code wie folgt verwenden:

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 

Das Bedingungsergebnis kann als Variable gespeichert werden.

Sergey Shoshin
quelle