2009-06-05 9 views
15

Ich versuche, die „MIT“ Anweisung in SQL Server zu verwenden, 2005. Es scheint gut zu funktionieren, wenn ich so etwas tun:Multiple Select-Anweisungen SQL Server 2005 „MIT“ Statement mit

WITH MyBigProducts AS (SELECT * FROM Products WHERE Size='Big') 
SELECT Name FROM MyBigProducts 

Aber es scheitert wenn ich versuche, wie mehrere select-Anweisungen zu verwenden:

WITH MyBigProducts AS (SELECT * FROM Products WHERE Size='Big') 
SELECT Name FROM MyBigProducts 
SELECT Count(*) FROM MyBigProducts 

und die Fehlermeldung „Ungültige Objektnamen‚MyBigProducts‘“.

Kann ich etwas tun, um den Geltungsbereich der Tabelle "MyBigProducts" so zu erweitern, dass beide SELECT-Anweisungen enthalten sind?

Mein Beispiel ist eine Vereinfachung von meinem eigentlichen Code, um das Problem verursacht, so dass ich die Abzinsung nicht die Möglichkeit, dass die obige triviales Beispiel sollte Arbeit und dass es einen anderen Fehler in meiner SQL ist.

Ich habe versucht, ein BEGIN und END um die zwei SELECT-Anweisungen zu wickeln, aber der Parser konnte es nicht kompilieren.

Antwort

14

Wie Kane sagte, ist das CTE nur in der SQL-Anweisung verfügbar, in der es geschrieben ist. Ein andere mögliche Lösung, je nach den Besonderheiten Ihrer Situation wäre der COUNT (*) in der einzigen Abfrage enthalten:

;WITH MyBigProducts AS 
(
    SELECT 
      Name, 
      COUNT(*) OVER() AS total_count 
    FROM 
      Products 
    WHERE 
      Size = 'Big' 
) 
SELECT 
    Name, 
    total_count 
FROM 
    MyBigProducts 
+0

Wird das die Zählung der Gesamttabelle berechnet einmal für jeden Zeile in der Tabelle Produkte? Oder nur einmal für die ganze Abfrage? –

+0

Aus dem Abfrageplan sieht es so aus, dass er es einmal berechnet und dann diesen Skalarwert in die Ergebnisse einfügt. Ich weiß nicht, was die relativen Kosten sind, um es in die Ergebnisse zu integrieren (sondern nur eine Abfrage verwenden) oder den Wert einmal in einer zweiten Abfrage abzurufen. Auf einem so-so Server, der hier 5000 Zeilen zurück gab, war es nicht bemerkbar. –

14

Ich glaube, dass Common Table Expressions nur für die sofortige Verwendung gültig sind, weshalb Sie einen Fehler für die "SELECT Count (*) FROM MyBigProducts" erhalten. Um ein CTE wiederzuverwenden, sollten Sie stattdessen eine temporäre Tabelle verwenden

Bitte korrigieren Sie mich, wenn ich falsch liege.

2

CTE haben Anweisung lokalen Bereich und Sichtbarkeit. Wenn Sie einen größeren Umfang und mehr Sichtbarkeit für einen Tabellenausdruck wünschen, müssen Sie das CTE zu einer View- oder Tabellenwertfunktion machen.

Alternativ können Sie die Ausdrucksergebnisse in eine Tabellenvariable materialisieren, die lokal für den aktuellen Stapel oder eine temporäre Tabelle ist, deren Lebensdauer ebenfalls lokal für den aktuellen Stapel ist, deren Sichtbarkeit sich jedoch auf die gesamte Sitzung erstreckt.

-1
WITH n(id, name) AS 
    (SELECT id, name 
    FROM ABC 
    WHERE parent = 44 
     UNION ALL 
    SELECT m.id, m.name 
    FROM ABC as m, n 
    WHERE n.id = m.parent) 
SELECT * FROM n 
+0

Pflege um zu erarbeiten? Wie deine Antwort meine Frage anspricht, ist mir nicht klar ... –

0
CREATE TABLE tblEmployees 
(
    EmployeeID SMALLINT IDENTITY(1001,1) NOT NULL, 
    EmployeeName NVARCHAR(100) NOT NULL, 
    Department NVARCHAR(50) NOT NULL, 
    Designation NVARCHAR(50) NOT NULL, 
    JoiningDate DATETIME NOT NULL, 
    Salary  DECIMAL(10,2) NOT NULL, 
    [Description] NVARCHAR(1000) NULL 
) 

SELECT * FROM tblEmployees 

INSERT INTO tblEmployees(EmployeeName, Department, Designation, JoiningDate, Salary, [Description]) 
VALUES ('John Smith', 'IT Research', 'Research Analyst', '02/08/2005', 23000.00, 'John Smith is involved in the Research and Development since 2005') 

INSERT INTO tblEmployees(EmployeeName, Department, Designation, JoiningDate, Salary, [Description]) 
VALUES ('John Micheal', 'IT Operations', 'Manager', '07/15/2007', 15000.00, NULL) 

INSERT INTO tblEmployees(EmployeeName, Department, Designation, JoiningDate, Salary, [Description]) 
VALUES ('Will Smith', 'IT Support', 'Manager', '05/20/2006', 13000.00, 'Joined this year as IT Support Manager') 

INSERT INTO tblEmployees(EmployeeName, Department, Designation, JoiningDate, Salary, [Description]) 
VALUES ('Anna John', 'IT Support', 'Developer', '02/10/2008', 23000.00, 'Joined this year as IT Support Developer') 


DECLARE @EmpID AS SMALLINT 
DECLARE @SQLQuery AS NVARCHAR(500) 
SET @EmpID = 1001 
SET @SQLQuery = 'SELECT * FROM tblEmployees WHERE EmployeeID = ' + CAST(@EmpID AS NVARCHAR(10)) 
Print @SQLQuery 
EXECUTE(@SQLQuery) 


DECLARE @EmpID AS SMALLINT 
DECLARE @SQLQuery AS NVARCHAR(500) 
DECLARE @ParameterDefinition AS NVARCHAR(100) 
SET @EmpID = 1002 
SET @SQLQuery = 'SELECT * FROM tblEmployees WHERE EmployeeID = @EmpID' 
SET @ParameterDefinition = '@EmpID SMALLINT' 
EXECUTE sp_executesql @SQLQuery, @ParameterDefinition, @EmpID 



Create Procedure sp_EmployeeSelect 
    @EmployeeName NVarchar(100), 
    @Department NVarchar(50), 
    @Designation NVarchar(50), 
    @StartDate DateTime, 
    @EndDate DateTime, 
    @Salary Decimal(10,2)  
AS 
    Set NoCount ON 
    Declare @SQLQuery AS NVarchar(4000) 
    Declare @ParamDefinition AS NVarchar(2000) 
    Set @SQLQuery = 'Select * From tblEmployees where (1=1) ' 

    If @EmployeeName Is Not Null 
     Set @SQLQuery = @SQLQuery + ' And (EmployeeName = @EmployeeName)' 
    If @Department Is Not Null 
     Set @SQLQuery = @SQLQuery + ' And (Department = @Department)' 
    If @Designation Is Not Null 
     Set @SQLQuery = @SQLQuery + ' And (Designation = @Designation)' 
    If (@StartDate Is Not Null) AND (@EndDate Is Not Null) 
     Set @SQLQuery = @SQLQuery + ' And (JoiningDate BETWEEN @StartDate AND @EndDate)' 
    If @Salary Is Not Null 
     Set @SQLQuery = @SQLQuery + ' And (Salary >= @Salary)' 
    Set @ParamDefinition = '@EmployeeName NVarchar(100), 
       @Department NVarchar(50), 
       @Designation NVarchar(50), 
       @StartDate DateTime, 
       @EndDate DateTime, 
       @Salary Decimal(10,2)' 

    Exec sp_Executesql @SQLQuery, @ParamDefinition, @EmployeeName, @Department, @Designation, 
         @StartDate, @EndDate, @Salary 

    If @@ERROR <> 0 GoTo ErrorHandler 
    Set NoCount OFF 
    Return(0) 

ErrorHandler: 
    Return(@@ERROR) 
GO 


EXEC sp_EmployeeSelect 'John Smith', NULL, NULL, NULL, NULL, NULL 

EXEC sp_EmployeeSelect NULL, 'IT Operations', 'Manager', NULL, NULL, NULL 




DECLARE @EmpName AS NVARCHAR(50) 
DECLARE @SQLQuery AS NVARCHAR(500) 
SET @EmpName = 'John' 
SET @SQLQuery = 'SELECT * FROM tblEmployees WHERE EmployeeName LIKE '''+ '%' + @EmpName + '%' + '''' 
PRINT @SQLQuery 
EXECUTE sp_executesql @SQLQuery 



DECLARE @EmpID AS NVARCHAR(50) 
DECLARE @SQLQuery AS NVARCHAR(500) 
SET @EmpID = '1001,1003,1004,1002' 
SET @SQLQuery = 'SELECT * FROM tblEmployees WHERE EmployeeID IN(' + @EmpID + ')' 
EXECUTE sp_executesql @SQLQuery 


DECLARE @OrderBy AS NVARCHAR(50) 
DECLARE @SQLQuery AS NVARCHAR(500) 
SET @OrderBy = 'Department' 
SET @SQLQuery = 'SELECT * FROM tblEmployees Order By ' + @OrderBy 
EXECUTE sp_executesql @SQLQuery 


WITH RESULTS AS(
SELECT * FROM [dbo].[User] 
)`enter code here`