有时最困难的事情是知道如何提出正确的问题,但我会尝试。
我试图弄清楚一条SQL语句(我在Azure SQL中)将检索多行,组合一些列并从其他列创建新的别名列,所有这些都是从更大的列返回的选择语句。
像泥一样清楚?让我试着把它画出来。
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
所以我需要这样的东西:Select * Employees WHERE managerID = 5
然后使用具有指定managerID的所有员工的结果集,为返回的每个员工返回最后一个班级和一行中的下一个班级。
员工也可能有也可能没有最后一堂课和/或即将到来的课程。
我已经看到了许多不同的方法来使用临时表迭代行,或者与GROUP BY等结合使用。但我似乎无法理解我需要的组合。
答案 0 :(得分:2)
更好的解决方案......使用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
答案 1 :(得分:1)
这不是解决问题的唯一方法,但这是我想到的。它需要两个内部查询,一个用于获取最后一个类,另一个用于获取下一个类。
-- 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