如果不在右表中,则查询从左表中恢复记录

时间:2014-12-15 21:47:04

标签: sql sql-server

想象一下,有一个商店表:

  • ID
  • StoreNumber
  • BRANCHNAME

想象一下,有另一个" SalesData"表:

  • ID
  • StoreNumber
  • AmountAquired

始终填充商店表。 SalesData不是。它仅在以及何时填充。

我正在努力想出下面的查询,如果在给定的月份和年份没有记录,并且AmountAquired为空,那么它将为每个商店返回结果。

同时另一个增加的复杂性(可能是一个单独的查询)是将销售数据中没有数据的所有商店(使用StoreNumber上的连接)带回来的地方,但是如果有数据则只返回该商店的行包含数据,并忽略该商店没有数据的行。

我尝试过做左外连接和右外连接,但没有去。

SELECT s.* FROM Stores s
LEFT OUTER JOIN SalesData sd ON
sd.StoreNumber = s.StoreNumber
WHERE sd.Year = 2014 AND sd.Month = 11 AND sd.AmountAquired IS NULL.

这只会带回年和月是2014年和11年的记录(这并不奇怪,因为那是我在where子句中所说的!)

我想把它带回到记录中,其中salesdata中没有数据或者月份和年份与给定的参数匹配(除非NULL在列值中,否则不会用于任何其他月份或任何其他年份) )

它应该总是带回数据(几乎从商店表中显示所有商店......以及在销售数据表中找不到的任何数据(或者即使数据是在给定的月份和年份)用于没有数据的商店)

希望这是有道理的。

2 个答案:

答案 0 :(得分:1)

你能不能只为第二种情况切换到OR?

(sd.Year = 2014 AND sd.Month = 11) OR sd.AmountAquired IS NULL

在第一个示例中,您要求“给定月份和年份没有记录,而AmountAquired为空” - 但如果没有记录,则AmountAquired必然为NULL。 / p>

该查询只是:

SELECT
  s.*
FROM
  Stores s
  LEFT OUTER JOIN SalesData sd ON sd.StoreNumber = s.StoreNumber
WHERE
  sd.StoreNumber IS NULL

答案 1 :(得分:1)

对于此类查询,使用LEFT OUTER JOIN是正确的。您犯的错误是,在执行LEFT OUTER JOIN时,您需要将与右表相关的过滤器移动到加入on部分。

仅获得2014年11月缺少销售的商店:

SELECT s.* 
FROM Stores s
LEFT OUTER JOIN SalesData sd ON
sd.StoreNumber = s.StoreNumber
AND sd.Year = 2014 AND sd.Month = 11
WHERE sd.AmountAquired IS NULL --no sales are found

要获得2014年11月的所有销售,包括没有销售的商店,您可以这样做:

SELECT s.* 
FROM Stores s
LEFT OUTER JOIN SalesData sd ON
sd.StoreNumber = s.StoreNumber
AND sd.Year = 2014 AND sd.Month = 11