具有多个变量的T-SQL SELECT

时间:2018-12-25 18:13:02

标签: sql sql-server tsql select while-loop

我正在尝试使用SQL语句和NORTHWIND数据库获取此输出:

Employee Name:Nancy Davolio
Number of Sales:345
Total Sales:192107.60

Employee Name:Andrew Fuller
Number of Sales:241
Total Sales:166537.75

Employee Name:Janet Leverling
Number of Sales:321
Total Sales:202812.84

Employee Name:Margaret Peacock
Number of Sales:420
Total Sales:232890.85

Employee Name:Steven Buchanan
Number of Sales:117
Total Sales:68792.28

...以及另外4个条目

当我使用此语句时:

USE Northwind

DECLARE @EmployeeName VARCHAR(40),
        @NumberOfSales INT,
        @TotalSales DECIMAL(10,2),
        @Counter TINYINT = 1,
        @NumEmployees INT = IDENT_CURRENT('dbo.Employees');

WHILE @Counter < @NumEmployees
BEGIN
    --SELECT @EmployeeName = E.FirstName+' '+E.LastName
    --SELECT @NumberOfSales = count(od.OrderID)
    SELECT @TotalSales = SUM(unitprice * quantity * (1 - Discount))
    FROM Employees E
    JOIN Orders AS O ON O.EmployeeID = E.EmployeeID
    JOIN [Order Details] AS OD ON OD.OrderID = O.OrderID
    WHERE E.EmployeeID = @Counter

    PRINT 'Employee Name:       '--+ @EmployeeName;
    PRINT 'Number of Sales:     '--+ LTRIM(STR(@NumberOfSales));
    PRINT 'Total Sales:         '+CONVERT(varchar(10),@TotalSales);
    PRINT '';

    SET @Counter += 1;
END

我可以让每个选择单独工作,但是我无法弄清楚语法来获得单个SELECT语句来完成所有工作。我也应该可以使用三个SET语句来执行此操作,但是我也无法弄清楚。两种可能性的指针都很棒。任何帮助将不胜感激。

这是实际的步骤动词: “在循环中,使用SELECT语句检索每个员工的名字和姓氏,每个员工处理的订单数量以及每个员工的总销售额(您正在逐个处理每个员工)。您将需要将多个表连接在一起,并使用聚合函数获取计数和总计。将串联的全名,销售数量和总销售量分配给适当的变量。“

输出应位于“消息”选项卡中,除了上面列出的预期输出外,没有其他表格或格式。

2 个答案:

答案 0 :(得分:4)

不需要循环(如果可能,应避免使用RBAR - Row By Agonizing Row方法):

SELECT EmployeeID
       ,[Employee Name] = E.FirstName+' '+E.LastName
       ,[TotalSales] = SUM(unitprice * quantity * (1-Discount))
       ,[NumberOfSales] = COUNT(DISTINCT o.OrderID)
FROM Employees E
JOIN Orders AS O ON O.EmployeeID = E.EmployeeID
JOIN [Order Details] AS OD ON OD.OrderID = O.OrderID
GROUP BY E.EmployeeID, E.FirstName+' '+E.LastName
ORDER BY E.EmployeeID;

编辑:

循环版本-一次分配多个变量。

USE Northwind

DECLARE @EmployeeName VARCHAR(40),
        @NumberOfSales INT,
        @TotalSales DECIMAL(10,2),
        @Counter TINYINT = 1,
        @NumEmployees INT = IDENT_CURRENT('dbo.Employees');

WHILE @Counter < @NumEmployees
BEGIN
    SELECT @EmployeeName  = E.FirstName+' '+E.LastName
          ,@NumberOfSales = COUNT(DISTINCT o.OrderID)
          ,@TotalSales    = SUM(unitprice * quantity * (1 - Discount))
    FROM Employees E
    JOIN Orders AS O ON O.EmployeeID = E.EmployeeID
    JOIN [Order Details] AS OD ON OD.OrderID = O.OrderID
    WHERE E.EmployeeID = @Counter
    GROUP BY E.FirstName+' '+E.LastName;

    PRINT 'Employee Name:       '+ @EmployeeName;
    PRINT 'Number of Sales:     '+ LTRIM(STR(@NumberOfSales));
    PRINT 'Total Sales:         '+ CONVERT(varchar(10),@TotalSales);
    PRINT '';

    SET @Counter += 1;
END

请注意,当您有间隔时(例如,您从1开始到WHILE,使用IDENT_CURRENT循环可能效率很低,这可能是您的ID为1,5,200671的情况)并最终导致不必要的循环。


编辑2:

  

在选择中发生多个分配时,似乎需要使用GROUP BY

我添加了GROUP BY,因为FirstName和LastName没有用聚合函数包装。您可以跳过该子句,但随后需要添加MIN/MAX函数:

SELECT @EmployeeName  = MIN(E.FirstName)+' '+MIN(E.LastName)
      ,@NumberOfSales = COUNT(DISTINCT o.OrderID)
      ,@TotalSales    = SUM(unitprice * quantity * (1 - Discount))
FROM Employees E
JOIN Orders AS O ON O.EmployeeID = E.EmployeeID
JOIN [Order Details] AS OD ON OD.OrderID = O.OrderID
WHERE E.EmployeeID = @Counter;
-- and we are sure that all values for First/Last nane are the same because of  
-- WHERE E.EmployeeID = @Counter

相关:Group by clause

  

在标准SQL中,包含GROUP BY子句的查询不能引用选择列表中未在GROUP BY子句中命名的未聚合列

答案 1 :(得分:1)

这应该做到。我使用CROSS APPLY取消了设置,然后进行了相应的格式化。您可以在标题为“交叉应用取消透视的替代方法”的文章中阅读有关它的更多信息。由于SQL使用集合,因此从我的拙见来看,SQL的输入和输出应始终是集合。

恐怕格式化的方式可能不是SQL的工作,但仍然可以通过“单”选择语句作为设置操作来实现:

;WITH CTE AS 
(
SELECT 
        EMPLOYEENAME =    E.FirstName +' '+ E.LastName,  
        NUMBEROFORDERS =  COUNT(OD.OrderID),
        TOTALSALES =      SUM(unitprice * quantity * (1-Discount))

   FROM Employees E
   INNER JOIN Orders AS O ON O.EmployeeID = E.EmployeeID
   INNER JOIN [Order Details] AS OD ON OD.OrderID = O.OrderID
   GROUP BY E.FirstName + ' ' + E.LastName
)


SELECT COLNAME, ColValue
FROM CTE

CROSS APPLY ( VALUES ('Employe Name:', EMPLOYEENAME),
                     ('Number of Sales:', LTRIM(STR(NUMBEROFORDERS, 25, 5)) ),
                     ('Total Sales:', LTRIM(STR(TOTALSALES, 25, 5)) ),
                     ('','')

            ) A  (COLNAME, ColValue)

示例输出如下:

COLNAME             ColValue
-------------   | ------------- 
Employe Name:   | Nancy Davolio
Number of Sales:|  345.00000
Total Sales:    |  192107.60432