Probelm声明:
编写查询以返回每个供应商的2015年销售信息。我们希望将所有供应商都包括在结果集中,无论他们的产品是否在2015年出售。
使用前两个问题中的Sales.Orders和Sales.OrderLines确定销售。但是,由于我们是从供应商的角度要求此信息的,因此您还需要使用表Warehouse.StockItems和Purchasing.Suppliers。
结果集中所需的列为:
SupplierID -出现在表Purchasing.Suppliers中。
SupplierName -出现在表Purchasing.Suppliers中。
OrderCount -每个供应商在产品上下的订单数。
销售-下订单的小计,根据表Sales.OrderLines的数量和单价计算。应该对结果进行排序,以使销售额最高的供应商位于顶部。如果两个供应商的销售额相同,则下一个使用最高订单数的订单数。如果两个供应商的销售和订单数量相同,请使用升序的供应商名称作为最终的平局。这将确保确定的结果。
我正在使用WorldWideImporters
Microsoft示例数据库表。我试图返回2015 sales information
中每个供应商的Purchasing.Suppliers
。我将在相应的列中返回OrderCount
和Sum of the 2015 sales
。我在这里遇到joins
的问题,因为我必须将Suppliers
连接到Warehouse.StockItems
,然后将这些项目连接到具有OrderLines
字段的特定StockItemID
。
问题在于,通常我会将orders
加入orderlines
,这样我只能过滤orders
中的orderlines
中的2015
。但是,使用我指定的表结构,似乎必须将OrderLines
连接到Orders
。
所以我要做的是将join
的那些Orders
退回OrderLines
,以提供我习惯的结果。这是我尝试的解决方案:
<pre>
SELECT S.SupplierID
,S.SupplierName
,COUNT(DISTINCT O.OrderID) AS OrderCount
,ISNULL(SUM(OLP.Quantity * OLP.UnitPrice), 0.00) AS Sales
FROM Purchasing.Suppliers AS S
LEFT OUTER JOIN Warehouse.StockItems AS W ON S.SupplierID = W.SupplierID
LEFT OUTER JOIN Sales.OrderLines AS OL ON W.StockItemID = OL.StockItemID
LEFT OUTER JOIN Sales.Orders AS O ON OL.OrderID = O.OrderID
AND O.OrderDate BETWEEN '2015-01-01' AND '2015-12-31'
LEFT OUTER JOIN Sales.OrderLines AS OLP ON O.OrderID = OLP.OrderID
GROUP BY S.SupplierID
,S.SupplierName
ORDER BY Sales DESC
,OrderCount
,SupplierName;
</pre>
编辑:
结果:
希望所有supplier
都没有期望,甚至没有sales
或orders
的也是如此。我不确定所计算的sales
是否正确,也不确定如何验证。不知道是否有人在我的查询中发现缺陷。
我不知道这是正确的还是解决此问题的最有效方法。我确实有限制,只能使用joins
,不能使用subqueries
,unions
等。
在理解方面的任何帮助将不胜感激。谢谢。
答案 0 :(得分:0)
要在不考虑供应商或订单行的情况下对订单进行基准测试:
/* query 1 */
SELECT
COUNT(*) AS ordercount
FROM Sales.Orders AS o
WHERE o.OrderDate >= '20150101' AND o.OrderDate < '20160101'
然后在不考虑供应商的情况下对订单行进行基准测试:
/* query 2 */
SELECT
COUNT(DISTINCT o.OrderID) AS ordercount
, SUM(olp.Quantity * olp.UnitPrice) AS sales
FROM Sales.Orders AS o
INNER JOIN Sales.OrderLines AS olp ON olP.OrderID = o.OrderID
WHERE o.OrderDate >= '20150101' AND o.OrderDate < '20160101'
现在开始引入更多的联接,如果值改变,则最新的联接有问题:
/* query 3 */
SELECT
COUNT(DISTINCT o.OrderID) AS ordercount
, SUM(olp.Quantity * olp.UnitPrice) AS sales
FROM Sales.Orders AS o
INNER JOIN Sales.OrderLines AS olp ON olP.OrderID = o.OrderID
INNER JOIN Warehouse.StockItems AS w ON w.StockItemID = olp.StockItemID
WHERE o.OrderDate >= '20150101' AND o.OrderDate < '20160101'
然后:
/* query 4 */
SELECT
COUNT(DISTINCT o.OrderID) AS ordercount
, SUM(olp.Quantity * olp.UnitPrice) AS sales
FROM Sales.Orders AS o
INNER JOIN Sales.OrderLines AS olp ON olP.OrderID = o.OrderID
INNER JOIN Warehouse.StockItems AS w ON w.StockItemID = olp.StockItemID
INNER JOIN Purchasing.Suppliers s ON s.SupplierID = w.SupplierID
WHERE o.OrderDate >= '20150101' AND o.OrderDate < '20160101'
您当然不需要两次连接订单行,关于左连接,这取决于您要实现的目标,例如:
仅供应商在日期范围内下订单:
/* query 5 */
SELECT
s.SupplierID
, s.SupplierName
, COUNT(DISTINCT o.OrderID) AS ordercount
, ISNULL(SUM(olp.Quantity * olp.UnitPrice), 0.00) AS sales
FROM Purchasing.Suppliers s
INNER JOIN Warehouse.StockItems AS w ON s.SupplierID = w.SupplierID
INNER JOIN Sales.OrderLines AS olp ON w.StockItemID = olp.StockItemID
INNER JOIN Sales.Orders AS o ON olP.OrderID = o.OrderID
WHERE o.OrderDate >= '20150101'
AND o.OrderDate < '20160101' -- note: this is "the next" day
GROUP BY
s.SupplierID
, s.SupplierName
ORDER BY
sales DESC
, ordercount
, SupplierName;
所有具有库存参考的供应商:
/* query 6 */
SELECT
s.SupplierID
, s.SupplierName
, COUNT(DISTINCT o.OrderID) AS ordercount
, ISNULL(SUM(olp.Quantity * olp.UnitPrice), 0.00) AS sales
FROM Purchasing.Suppliers s
INNER JOIN Warehouse.StockItems AS w ON s.SupplierID = w.SupplierID
LEFT JOIN Sales.OrderLines AS olp ON w.StockItemID = olp.StockItemID
LEFT JOIN Sales.Orders AS o ON olP.OrderID = o.OrderID
AND o.OrderDate >= '20150101'
AND o.OrderDate < '20160101' -- note: this is "the next" day
GROUP BY
s.SupplierID
, s.SupplierName
ORDER BY
sales DESC
, ordercount
, SupplierName;
每个供应商:
/* query 7 */
SELECT
s.SupplierID
, s.SupplierName
, COUNT(DISTINCT o.OrderID) AS ordercount
, ISNULL(SUM(olp.Quantity * olp.UnitPrice), 0.00) AS sales
FROM Purchasing.Suppliers s
LEFT JOIN Warehouse.StockItems AS w ON s.SupplierID = w.SupplierID
LEFT JOIN Sales.OrderLines AS olp ON w.StockItemID = olp.StockItemID
LEFT JOIN Sales.Orders AS o ON olP.OrderID = o.OrderID
AND o.OrderDate >= '20150101'
AND o.OrderDate < '20160101' -- note: this is "the next" day
GROUP BY
s.SupplierID
, s.SupplierName
ORDER BY
sales DESC
, ordercount
, SupplierName;
请注意在日期范围内使用between
,定义日期范围的最可靠方法是使用>=
和<
,如上所示,不管数据的时间精度是多少。 YYYYMMDD也是TSQL中最安全的日期文字格式。