0

我有一个基于位置跟踪零售销售的数据库。我有一个带有 ID 和各种其他位置特定信息的位置表,一个带有 itemID 和所有其他项目信息的零售项目表,以及一个包含位置和项目 ID 以及其他信息的零售使用表销售(数量、销售价格等)。我正在尝试进行查询,该查询将返回所有零售商品以及按位置分组的给定日期范围内每个商品的销售量总和。

我发现了这个SO question 并在一定程度上模仿了 Tony Andrews 的回答,但它并没有达到我的预期。

如果我不包括日期范围,我可以获得完整的商品列表(所有 29 件商品都按预期重新调整)和销售数量:

SELECT i.WholesaleCost, i.RetailPrice, i.OnHandQuan, u.ItemNo, AVG(u.Price) AS Price, SUM(u.Quantity) AS Quantity, l.Description, l.LocationID, i.Description AS ItemDescription 
FROM Location as l CROSS JOIN RetailSaleItems as i
  INNER JOIN RetailSaleUsage as u ON l.LocationID = i.LocationID AND i.ItemNo = u.ItemNo
WHERE (l.LocationID IN(1)) AND (i.Inactive = 0)
GROUP BY i.WholesaleCost, i.RetailPrice, i.OnHandQuan, u.ItemNo, l.[Description], l.LocationID, i.[Description]
ORDER BY l.[Description]

一旦我尝试限制日期范围,比如今年 1 月,我就会丢失 5 条记录,并且尽我所能告诉它,因为它们没有显示在指定日期范围内的 RetailSaleusage 表中。但这没有任何意义,因为还有 15 个其他项目也没有出现在该日期范围内,但它们出现在结果中。

我使用的日期范围的 SQL 是:

SELECT i.WholesaleCost, i.RetailPrice, i.OnHandQuan, u.ItemNo, AVG(u.Price) AS Price, SUM(u.Quantity) AS Quantity, l.Description, l.LocationID, i.Description AS ItemDescription 
FROM Location as l CROSS JOIN RetailSaleItems as i
  INNER JOIN RetailSaleUsage as u ON l.LocationID = i.LocationID AND i.ItemNo = u.ItemNo
WHERE (l.LocationID IN(1)) 
  AND (i.Inactive = 0) AND (u.[Date] >= '1/1/2013' AND u.[Date] <= '1/31/2013')
GROUP BY i.WholesaleCost, i.RetailPrice, i.OnHandQuan, u.ItemNo, l.[Description], l.LocationID, i.[Description]
ORDER BY l.[Description]

我在 MSDN 上找到了这篇文章,该文章讨论了交叉连接在包含where子句时的行为类似于内部连接,但其中一条评论指出,这只适用于where规定连接条件的情况。由于where我的 SQL 只是限制日期范围,我假设这不是问题。

对此的任何指导将不胜感激。

4

1 回答 1

2

您可能不需要CROSS JOIN. 它们在实践中并没有太多使用(很少,它们非常有用,但很少)。

无论如何,您可能想对 s 进行一些研究[LEFT|RIGHT] [OUTER] JOINOUTER关键字是可选的)。使用INNER JOINs,记录必须存在于每个连接的表中。使用OUTER JOINs,一条记录必须至少存在一个表中才能返回数据。哪个表取决于您执行的是 aLEFT JOIN还是RIGHT JOIN.

我已经尝试在下面编写正确的查询 - 但我不知道您的数据模型并做了一些“直觉猜测”。玩这个,看看你能想出什么。

SELECT i.WholesaleCost, i.RetailPrice, i.OnHandQuan, u.ItemNo, AVG(u.Price) AS Price, SUM(u.Quantity) AS Quantity, l.Description, l.LocationID, i.Description AS ItemDescription 
FROM Location as l 
    INNER JOIN RetailSaleItems as i ON i.LocationID = l.LocationID
    LEFT JOIN RetailSaleUsage as u ON l.LocationID = u.LocationID
WHERE (l.LocationID IN(1)) AND (i.Inactive = 0) AND (i.ItemNo = u.ItemNo OR u.ItemNo IS NULL)
GROUP BY i.WholesaleCost, i.RetailPrice, i.OnHandQuan, u.ItemNo, l.[Description], l.LocationID, i.[Description]
ORDER BY l.[Description]

更新:为了帮助您根据下面的评论回答您的问题,您需要更改按日期范围限制的位置。目前,您将所有结果限制在RetailSaleUsage表中的指定日期范围内,因为条件放置在WHERE子句中。相反,我们需要将限制指定为JOIN加入RetailSaleUsage表的条件。看看下面的查询。那应该为你做。

SELECT i.WholesaleCost, i.RetailPrice, i.OnHandQuan, u.ItemNo, AVG(u.Price) AS Price, SUM(u.Quantity) AS Quantity, l.Description, l.LocationID, i.Description AS ItemDescription 
FROM Location as l 
    INNER JOIN RetailSaleItems as i ON i.LocationID = l.LocationID
    LEFT JOIN RetailSaleUsage as u ON l.LocationID = u.LocationID AND u.[Date] BETWEEN '1/1/2013' AND '1/31/2013'
WHERE (l.LocationID IN(1)) AND (i.Inactive = 0) AND (i.ItemNo = u.ItemNo OR u.ItemNo IS NULL)
GROUP BY i.WholesaleCost, i.RetailPrice, i.OnHandQuan, u.ItemNo, l.[Description], l.LocationID, i.[Description]
ORDER BY l.[Description]

HTH。

于 2013-07-12T17:47:03.103 回答