2009-06-05 14 views
15

Estoy tratando de utilizar la expresión "with" en SQL Server 2005. Parece que funciona bien si hago algo como:múltiples Sentencias Select utilizando SQL Server 2005 "CON" Declaración

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

pero fracasa si trato de usar múltiples sentencias de selección como:

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

y el mensaje de error es " '' MyBigProducts nombre de objeto no válido".

¿Hay algo que pueda hacer para aumentar el alcance de la tabla "MyBigProducts" para incluir ambas declaraciones select?

Mi ejemplo es una simplificación de mi código real que causa el problema, por lo que no estoy descartando la posibilidad de que el ejemplo trivial anterior funcione y que haya otro error en mi SQL.

He intentado envolver un BEGIN y END alrededor de las dos instrucciones SELECT, pero el analizador no pudo compilarlo.

Respuesta

14

Como dijo Kane, el CTE solo está disponible en la declaración SQL donde está escrito. Otra solución posible, dependiendo de los detalles de su situación, sería incluir el COUNT (*) en la misma consulta:

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

¿Esta calcular el recuento de la tabla general una vez por cada fila en la tabla Productos? ¿O solo una vez para toda la consulta? –

+0

Parece que desde el plan de consulta aquí lo calcula una vez y luego combina ese valor escalar en los resultados. No sé cuál es el costo relativo para fusionarlo en los resultados (pero solo teniendo que usar una consulta) versus obtener el valor una vez en una segunda consulta. En un servidor regular aquí devolviendo 5000 filas era imperceptible. –

14

Creo que las Expresiones de tablas comunes son solo válidas para el uso inmediato y es por eso que se obtiene un error para "SELECT Count (*) FROM MyBigProducts". Para reutilizar un CTE, debe usar una tabla temporal en su lugar

DECALRE @BigProducts TABLE (...[declaration omitted]...) 

INSERT INTO @BigProducts 
SELECT * 
FROM Products 
WHERE Size='Big' 


SELECT Name FROM @BigProducts 
SELECT Count(*) FROM @BigProducts 

Corrija mi error si me equivoco.

2

CTE tienen alcance local de la declaración y visibilidad. Si desea mayor alcance y visibilidad para una expresión de tabla, debería hacer que el CTE se convierta en una función de Vista o de valor de tabla.

Como alternativa, puede materializar los resultados de expresiones en una variable de tabla, local para el lote actual o una tabla temporal cuya duración también es local para el lote actual, pero cuya visibilidad se extiende a toda la sesión.

-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

¿Cuidar para elaborar? No está claro cómo responde tu respuesta a mi pregunta ... –

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` 
Cuestiones relacionadas