好吧,我是SQL的初学者,所以如果这个问题对你来说太新手了,请原谅。 在Northwind(我确定每个人都知道Northwind) - 我每个月都试图获得最多销售的产品(按数量计算)和1997年销售最少的产品 (使用订单,订单详情,产品表)
由于
更新: 这就是我到目前为止所拥有的
Select p.productname,
Datepart(MM,o.OrderDate),
od.Quantity
from orders o
inner join [Order Details] od
on o.OrderID = od.OrderID
inner join Products p
on p.ProductID=od.ProductID
Where YEAR(o.OrderDate)=1997
Group by Datepart(MM,o.OrderDate), od.Quantity,p.productname
答案 0 :(得分:2)
这不是新手问题。这是一个常见的,但也有一个人很难做到正确。他们经常使用多个SQL语句。
但是你,我的朋友,很幸运!您即将与我一起进入分析功能的世界。但请放心 - 如果不符合您的口味,还有其他方法可以解决这个问题。
我假设你只是在修补SQL,只是想要了解更多。如果您实际上是在尝试解决某个特定问题,那么如果您可以更加具体地解决这两点问题,那将会有所帮助:
SQL:
WITH
ProductSalesPerMonth AS
(
SELECT
DATEPART(MM, O.OrderDate) AS MonthNum,
OD.ProductID,
SUM(OD.Quantity) AS Quantity
FROM
Orders O
JOIN [Order Details] OD
ON O.OrderID = OD.OrderID
WHERE
O.OrderDate BETWEEN '19970101' AND '19971231'
GROUP BY
DATEPART(MM, O.OrderDate),
OD.ProductID
),
RankedProductSalesPerMonth AS
(
SELECT
PSPM.*,
ROW_NUMBER() OVER (PARTITION BY PSPM.MonthNum ORDER BY PSPM.Quantity ASC) AS Rank_SoldLeast,
ROW_NUMBER() OVER (PARTITION BY PSPM.MonthNum ORDER BY PSPM.Quantity DESC) AS Rank_SoldMost
FROM
ProductSalesPerMonth PSPM
)
SELECT
PS.MonthNum,
P.ProductName,
PS.Quantity,
CASE
WHEN Rank_SoldMost = 1 THEN 'Top Seller'
WHEN Rank_SoldLeast = 1 THEN 'Bottom Seller'
ELSE 'Only Seller'
END AS SalesRank
FROM
RankedProductSalesPerMonth PS
JOIN Products P
ON P.ProductID = PS.ProductID
WHERE
(Rank_SoldMost = 1 OR Rank_SoldLeast = 1)
ORDER BY
MonthNum ASC,
Quantity DESC
;
输出:
MonthNum ProductName Quantity SalesRank
1 Geitost 119 Top Seller
1 Konbu 2 Bottom Seller
2 Pâté chinois 180 Top Seller
2 Gorgonzola Telino 3 Bottom Seller
3 Raclette Courdavault 162 Top Seller
3 Konbu 1 Bottom Seller
也许你看到这个并说“Jeezuz!”,所以这里是对代码的快速解释。
WITH允许您组合一种称为“公用表表达式”的子查询。在SQL Server中,它应该像视图一样工作。 CTE可以互相参考。我正在使用它们,因为我认为理解各个组件要比一个大的SELECT更容易,你在任何地方引用DATEPART(MM, O.OrderDate)
和SUM(OD.Quantity)
。它还允许我们推迟连接表(如Product
),直到我们真正需要这些信息。
我们的第一个条款按月对每个产品进行分组和汇总。就是这样。
第二个条款确定了最高和最低卖家。在SQL Server中,从组中查找一条记录的常用方法是进行分区和排序,以便将您想要的记录冒泡到排序列表的顶部。通过按数量DESC排序,我们的畅销商将在Ranked_SoldMost列中获得“1”。底部卖家类似。
第三个条款允许我们过滤到我们的顶部/底部卖家,然后使用产品信息装饰ProductID。
就是这样。如果这不是你要求的,或者你有疑问,那就开火吧。
答案 1 :(得分:1)
我提出了解决问题的解决方案。 它是一个包含3个子选择的select语句,但它可以工作,并且在同一行上销售最多且销售最少的产品:
select
a.month,
(select top 1
p.ProductName as pid
from Northwind.dbo.[Order Details] od1
left join Northwind.dbo.Orders o on o.OrderID = od1.OrderID
left join Northwind.dbo.Products p on p.ProductID = od1.ProductID
where
YEAR(o.OrderDate)=1997 and
DATEPART(MM,o.OrderDate) = a.month
group by
p.ProductName,
DATEPART(MM,o.OrderDate)
having
sum(od1.Quantity) = MAX(a.qty)),
max(a.qty) as maxQty,
(select top 1
p.ProductName as pid
from Northwind.dbo.[Order Details] od1
left join Northwind.dbo.Orders o on o.OrderID = od1.OrderID
left join Northwind.dbo.Products p on p.ProductID = od1.ProductID
where
YEAR(o.OrderDate)=1997 and
DATEPART(MM,o.OrderDate) = a.month
group by
p.ProductName,
DATEPART(MM,o.OrderDate)
having
sum(od1.Quantity) = MIN(a.qty)),
min(a.qty) as minQty
from
(select
p.ProductName as pid,
DATEPART(MM,o.OrderDate) as month,
sum(od1.Quantity) as qty
from Northwind.dbo.[Order Details] od1
left join Northwind.dbo.Orders o on o.OrderID = od1.OrderID
left join Northwind.dbo.Products p on p.ProductID = od1.ProductID
where
YEAR(o.OrderDate)=1997
group by
p.ProductName,
DATEPART(MM,o.OrderDate)) as a
group by
a.month
我确信使用一些临时表格可以做得更聪明
答案 2 :(得分:0)
很难说出你在问什么,特别是当你没有为你的桌子提供任何模式时。但是,要开始学习SQL中的JOIN语句,我建议Jeff Atwood's Visual Guide