我正在接受SQL Server培训并完成了这项任务:
按月显示1997年每位员工的销售量。结果应包含108条记录(9 * 12)。只有一个查询
我正在使用Northwind示例数据库。
我的查询:
Select
dbo.Employees.EmployeeID
, dbo.Employees.FirstName
, dbo.Employees.LastName
, MONTH(OrderDate) as [Month]
--, YEAR(OrderDate) as [Year]
, sum([Order Details].Quantity*[Order Details].UnitPrice) as [Sales Volume]
from
Orders
Inner join
dbo.[Order Details] on dbo.[Order Details].OrderID = dbo.Orders.OrderID
Inner join
dbo.Employees on dbo.Employees.EmployeeID = dbo.Orders.EmployeeID
where
DATEPART(year, OrderDate) = 1997
group by
Month(OrderDate),
dbo.Employees.EmployeeID, dbo.Employees.FirstName,
dbo.Employees.LastName
order by
dbo.Employees.EmployeeID;
不幸的是,我只获得了104条记录,因为它们是几个月,当时员工没有任何订单(例如我想将其设置为0)。
我知道,我需要一个日历表或特殊的子查询。但我无法解决它(大约2天)。
我发现了类似的内容,但我无法将此代码块添加到我的解决方案中。
Select
DATEADD(MONTH, n, DATEADD(MONTH, DATEDIFF(MONTH, 0, '1997-01-01'), 0)) StartDate,
DATEADD(MONTH, n+1, DATEADD(MONTH, DATEDIFF(MONTH, 0, '1997-01-01'), 0)) EndDate
FROM
(SELECT TOP 12
(ROW_NUMBER() OVER (ORDER BY CustomerID) - 1) as n
FROM Orders) as n
是的,有人能帮帮我吗?
答案 0 :(得分:1)
此处有查询,需要SQL Server 2008或更高版本:
WITH Months AS
(
SELECT *
FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) AS M(MonthNumber)
)
, EmployeesMonths AS
(
SELECT
E.EmployeeID, E.FirstName, E.LastName, Months.MonthNumber
FROM
dbo.Employees E
CROSS JOIN Months
)
, SalesSummary AS
(
SELECT
O.EmployeeID,
MONTH(O.OrderDate) AS MonthNumber,
SUM(OD.UnitPrice * OD.Quantity * (1 - OD.Discount)) AS Sales
FROM
dbo.Orders O
INNER JOIN dbo.[Order Details] OD
ON O.OrderID = OD.OrderID
WHERE
YEAR(O.OrderDate) = 1997
GROUP BY
O.EmployeeID, MONTH(O.OrderDate)
)
SELECT
EM.EmployeeID, EM.FirstName, EM.LastName, EM.MonthNumber,
CAST(ISNULL(SS.Sales, 0) AS decimal(18,2)) AS Sales
FROM
EmployeesMonths EM
LEFT OUTER JOIN SalesSummary SS
ON EM.EmployeeID = SS.EmployeeID AND EM.MonthNumber = SS.MonthNumber
ORDER BY
EM.EmployeeID, EM.MonthNumber
编辑: 以上查询使用链式CTE(Common Table Expresions)。链式CTE允许您逐步处理您的问题,您不需要立即考虑整个问题。首先,我们需要数月,然后我们需要员工和月份的笛卡尔积。还需要按月和员工的销售摘要。最后,我们在最后一次查询时将所有内容粘合在一起。
答案 1 :(得分:0)
尝试以下内容:
DECLARE @o TABLE
(
orderid INT ,
empid INT ,
orderdate DATETIME ,
amount MONEY
)
DECLARE @e TABLE
(
empid INT ,
name NVARCHAR(MAX)
)
INSERT INTO @e
VALUES ( 1, 'Bob' ),
( 2, 'Peter' ),
( 3, 'Charley' )
INSERT INTO @o
VALUES ( 1, 1, '20140101', 100 ),
( 1, 1, '20150101', 1 ),
( 2, 1, '20150102', 2 ),
( 3, 1, '20150201', 2.5 ),
( 4, 2, '20150101', 4 ),
( 5, 2, '20150103', 20 ),
( 6, 2, '20150104', 1 )
SELECT m.id ,
e.empid ,
e.name ,
ISNULL(SUM(o.amount), 0) AS summ
FROM ( VALUES ( 1), ( 2), ( 3), ( 4), ( 5), ( 6), ( 7), ( 8), ( 9), ( 10),
( 11), ( 12) ) AS m ( id )
CROSS JOIN @e e
LEFT JOIN @o o ON m.id = MONTH(o.orderdate) AND e.empid = o.empid
WHERE DATEPART(year, OrderDate) = 2015 OR o.orderid IS NULL
GROUP BY m.id ,
e.empid ,
e.name
ORDER BY e.empid, m.id
输出:
id empid name summ
1 1 Bob 3.00
2 1 Bob 2.50
3 1 Bob 0.00
4 1 Bob 0.00
5 1 Bob 0.00
6 1 Bob 0.00
7 1 Bob 0.00
8 1 Bob 0.00
9 1 Bob 0.00
10 1 Bob 0.00
11 1 Bob 0.00
12 1 Bob 0.00
1 2 Peter 25.00
2 2 Peter 0.00
3 2 Peter 0.00
4 2 Peter 0.00
5 2 Peter 0.00
6 2 Peter 0.00
7 2 Peter 0.00
8 2 Peter 0.00
9 2 Peter 0.00
10 2 Peter 0.00
11 2 Peter 0.00
12 2 Peter 0.00
1 3 Charley 0.00
2 3 Charley 0.00
3 3 Charley 0.00
4 3 Charley 0.00
5 3 Charley 0.00
6 3 Charley 0.00
7 3 Charley 0.00
8 3 Charley 0.00
9 3 Charley 0.00
10 3 Charley 0.00
11 3 Charley 0.00
12 3 Charley 0.00
答案 2 :(得分:0)
Select
dbo.Employees.EmployeeID
, dbo.Employees.FirstName
, dbo.Employees.LastName
, [Month].[Month]
--, YEAR(OrderDate) as [Year]
, sum([Order Details].Quantity*[Order Details].UnitPrice) as [Sales Volume]
from dbo.Employees
CROSS JOIN (
SELECT 1 [month]
UNION SELECT 2
UNION SELECT 3
UNION SELECT 4
UNION SELECT 5
UNION SELECT 6
UNION SELECT 7
UNION SELECT 8
UNION SELECT 9
UNION SELECT 10
UNION SELECT 11
UNION SELECT 12
) [month]
LEFT JOIN Orders on dbo.Employees.EmployeeID = dbo.Orders.EmployeeID AND [month].[month]=Month(OrderDate)
LEFT join dbo.[Order Details] on dbo.[Order Details].OrderID = dbo.Orders.OrderID
where DATEPART(year, OrderDate) = 1997
group by [Month].[Month], dbo.Employees.EmployeeID, dbo.Employees.FirstName, dbo.Employees.LastName
order by dbo.Employees.EmployeeID;