Sql 左联接不仅保留SELECT查询中出现的记录

Sql 左联接不仅保留SELECT查询中出现的记录,sql,sql-server,join,Sql,Sql Server,Join,我使用以下SQL select语句获取产品或葡萄酒的子集: SELECT pv.SkProdVariantId AS id, pa.Colour AS colour, FROM Dim.ProductVariant AS pv JOIN ProductAttributes_new AS pa ON pv.SkProdVariantId = pa.SkProdVariantId WHERE pv.ProdTypeName = 'Wines' 生成的此表的长度为39

我使用以下SQL select语句获取产品或葡萄酒的子集:

SELECT pv.SkProdVariantId AS id,
       pa.Colour AS colour,
  FROM Dim.ProductVariant AS pv
  JOIN ProductAttributes_new AS pa
    ON pv.SkProdVariantId = pa.SkProdVariantId
 WHERE pv.ProdTypeName = 'Wines'
生成的此表的长度为3905。我想获取这些产品的所有事务数据。 目前我正在使用这个select语句

SELECT c.CalDate AS timestamp,
       f.SkProductVariantId AS sku_id,
       f.Quantity AS quantity
  FROM fact.FTransactions AS f
LEFT JOIN Dim.Calendar AS c
          ON f.SkDateId = c.SkDateId
LEFT JOIN (    
  SELECT pv.SkProdVariantId AS id,
         pa.Colour AS colour,
    FROM Dim.ProductVariant AS pv
    JOIN ProductAttributes_new AS pa
      ON pv.SkProdVariantId = pa.SkProdVariantId
   WHERE pv.ProdTypeName = 'Wines'  
  ) AS s
  ON s.id = f.SkProductVariantId
 WHERE c.CalDate LIKE '%2019%'
日历日期正确,但返回的唯一产品数为5648,而不是select查询中预期的3905

为什么我在第一个select查询中的左连接没有像我期望的那样工作


谢谢你的帮助

如果希望所有行构成查询,则它需要是左联接中的第一个引用。那么,我猜您希望在2019年进行交易:

select . . .
from (SELECT pv.SkProdVariantId AS id, pa.Colour AS colour,
      FROM Dim.ProductVariant pv JOIN
           ProductAttributes_new pa
           ON pv.SkProdVariantId = pa.SkProdVariantId
      WHERE pv.ProdTypeName = 'Wines'
     ) s LEFT JOIN
     (fact.FTransactions f JOIN
      Dim.Calendar c
      ON f.SkDateId = c.SkDateId AND
         c.CalDate >= '2019-01-01' AND
         c.CalDate < '2020-01-01'
     )
     ON s.id = f.SkProductVariantId;

注意,这假设CalDate实际上是一个日期而不是字符串。LIKE应该只用于字符串。

您误解了外部联接的工作原理。请看戈登的回答和我的要求

至于任务:似乎您希望选择2019年的交易,但您希望将结果限制在葡萄酒产品上。我们通常在WHERE子句中限制查询结果。您可以在中使用,也可以为此而存在

SELECT
  c.CalDate AS timestamp,
  f.SkProductVariantId AS sku_id,
  f.Quantity AS quantity
FROM fact.FTransactions AS f
INNER JOIN Dim.Calendar AS c ON f.SkDateId = c.SkDateId
WHERE DATEPART(YEAR, c.CalDate) = 2019
AND f.SkProductVariantId IN
(
  SELECT pv.SkProdVariantId
  FROM Dim.ProductVariant AS pv
  WHERE pv.ProdTypeName = 'Wines'
);

我已经删除了与ProductAttributes\u new的联接,因为它似乎在该查询中没有任何作用。

如果联接中匹配的行数为>1@Charlieface这正是我所期望的,因为一个产品可能会有很多交易。但是,我看到的是,第二个表中有比第一个表中更多的唯一SKU ID,这肯定是不正确的?您选择的是2019年的所有交易。LEFT JOIN Dim.Calendar实际上是一个内部JOIN Dim.Calendar,因为对于像“%2019%”这样的WHERE c.CalDate,如果存在任何外部联接行,您将忽略所有外部联接行,我对此表示怀疑。然后加入葡萄酒信息。结果,你将拥有2019年的所有交易,winy将拥有额外的葡萄酒信息。这一定是我出错的地方,我会尽快尝试。。。谢谢感谢您的帮助,并澄清了几点。