交叉连接行为

时间:2013-07-12 17:11:22

标签: sql

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

我发现了this这个问题并且模仿了托尼·安德鲁斯对某一点的回答,但这并没有像我期望的那样发挥作用。

如果我不包含日期范围,我可以获得完整的商品清单(所有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个其他项目在该日期范围内没有出现,但它们出现在结果中。

我使用的日期范围是:

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上发现了this文章,其中讨论了当包含where子句时,内部联接的交叉联接,但其中一条注释表明仅在where指示时才适用加入标准。由于我的SQL的where只是限制了日期范围,所以我认为这不是问题。

对此的任何指示都将非常感激。

1 个答案:

答案 0 :(得分:2)

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

无论如何,您可能希望对[LEFT|RIGHT] [OUTER] JOIN进行一些研究(OUTER关键字是可选的)。使用INNER JOIN s时,每个连接的表中都必须存在记录。对于OUTER JOIN s,必须在至少一个表中存在记录才能返回数据。哪个表格取决于您是在执行LEFT 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。