【问题标题】:SQL combine rows and create columnsSQL 合并行并创建列
【发布时间】:2014-07-16 12:59:00
【问题描述】:

有时最难的是知道如何提出正确的问题,但我会尝试一下。
我试图找出一个 SQL 语句(我在 Azure SQL 中),它将检索多行、组合一些列并从其他列创建新的别名列,所有这些都是从更大的 select 语句返回的每一行。 清如泥?让我试着画出来。

    Employees    
    ------------
    employeeID  |  managerID | fname
     1                 5        Bill
     2                 5        John
     3                 6        Mary


ClassRegistration
-----------------
employeeID   |  classID
  1               25
  2               25
  1               27
  1               28
  2               30
  1               45
  1               55
  2               35


Classes
----------
classID  |   classStartDate 
   25           7/1/2014
   27           7/14/2014
   28           7/28/2014
   30           7/11/2014
   35           8/1/2014
   45           8/1/2014

我需要返回的是这样的表格:

Employee fname  |  Last Class |  Upcoming Class 
 Bill                 27              28
 John                 30              35

所以我需要类似的东西:选择 * 员工 WHERE managerID = 5。
然后使用具有指定 managerID 的所有员工的结果集,为返回的每个员工返回一行中的最后一个类和下一个类。
此外,员工可能有也可能没有最后一堂课和/或即将上课。

我已经看到了许多不同的方法来使用临时表或与 GROUP BY 组合等来遍历行。但我似乎无法理解我需要什么组合。

【问题讨论】:

    标签: sql tsql azure


    【解决方案1】:

    更好的解决方案...使用over 子句...

    SELECT DISTINCT E.empId, E.managerid, e.fname,    
                    Max(lastclass.classStartDate) over(partition by e.empId) as lastClass,
                    Min(nextClass.classStartDate) over(partition by e.empId) as nextClass
    FROM [T_employees] E
    INNER JOIN T_ClassRegistration CR on E.empId = CR.empid   
    LEFT JOIN T_Classes lastclass on CR.classid = lastclass.classid 
                                 and lastclass.classStartDate <= getdate()
    LEFT JOIN T_Classes nextClass on CR.classid = nextClass.classid 
                                 and nextClass.classStartDate> getdate()
    WHERE managerId = 5
    

     

    【讨论】:

    • 这将给出最后一个和下一个课程的开始日期,但要求是返回课程 ID。
    【解决方案2】:

    这不是解决它的唯一方法,但这是我想到的。它需要两个内部查询,一个获取最后一个类,一个获取下一个类。

    -- For testing the query, lets set hardcoded date.  Normally one might use GETDATE()
    DECLARE @today DATE = '2014-07-16'
    
    SELECT
      e.FName,
      (
        -- Get the class with the highest ClassStartDate which started before today
        SELECT TOP 1 c.ClassID
        FROM ClassRegistration cr
          INNER JOIN Classes c on c.ClassID = cr.ClassId
        WHERE cr.EmployeeID = e.EmployeeID
          AND c.ClassStartDate < @today
        ORDER BY ClassStartDate DESC
      ) AS LastClass,
      (
        -- Get the class with the lowest ClassStartDate which started after, or including, today
        SELECT TOP 1 c.ClassID
        FROM ClassRegistration cr
          INNER JOIN Classes c on c.ClassID = cr.ClassId
        WHERE cr.EmployeeID = e.EmployeeID
          AND c.ClassStartDate >= @today
        ORDER BY ClassStartDate ASC
      ) AS NextClass
    FROM Employees e
    ORDER BY FName
    

    如果您想按之前课程中注册的员工进行过滤,则类似:

    SELECT * FROM (
      SELECT
        e.FName,
        (
          -- Get the class with the highest ClassStartDate which started before today
          SELECT TOP 1 c.ClassID
          FROM ClassRegistration cr
            INNER JOIN Classes c on c.ClassID = cr.ClassId
          WHERE cr.EmployeeID = e.EmployeeID
            AND c.ClassStartDate < @today
          ORDER BY ClassStartDate DESC
        ) AS LastClass,
        (
          -- Get the class with the lowest ClassStartDate which started after, or including, today
          SELECT TOP 1 c.ClassID
          FROM ClassRegistration cr
                INNER JOIN Classes c on c.ClassID = cr.ClassId
              WHERE cr.EmployeeID = e.EmployeeID
                AND c.ClassStartDate >= @today
              ORDER BY ClassStartDate ASC
            ) AS NextClass
      FROM Employees e
    ) t
    WHERE NextClass IS NOT NULL
    ORDER BY FName
    

    【讨论】:

    • 感谢您的帮助!我选择另一个答案是最好的,因为它看起来更干净。
    • 这是一个更好的答案。我什至没有想过使用 min/max 作为窗口函数。
    猜你喜欢
    • 2020-06-09
    • 1970-01-01
    • 2023-03-19
    • 2021-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    相关资源
    最近更新 更多