LEFT JOIN条件

时间:2012-08-28 04:38:02

标签: sql sql-server-2008 inner-join

我正在使用MS SQL。我有两张桌子:

1)“OrderProducts” - 此表存储订单的所有产品。还有另一个Orders主表,我们可以从这张图中省略。订单主表存储订单的主数据,而OrderProducts表存储详细信息。

2)“TransactionFeeProducts” - 此表存储我想要为订单收取的所有产品的交易费用。它有一个BatchID,其中多个产品可以具有相同的BatchID。

基本上,OrderDate所有订购的产品介于TransactionFeeProducts.FromDate和TransactionFeeProducts.ToDate之间,将收取TransactionFeeProducts.TransactionFee

OrderProducts

  • 的ProductID
  • 数量
  • 订购日期

TransactionFeeProducts

  • BatchID
  • 的ProductID
  • FROM日期
  • TODATE
  • TransactionFee

SQL:

SELECT SUM(Quantity) as Orders, 
TransactionFeeProducts.ProductID, FromDate, ToDate 
FROM TransactionFeeProducts 
LEFT JOIN OrderProducts ON TransactionFeeProducts.ProductID = OrderProducts.ProductID
WHERE
OrderDate >= TransactionFeeProducts.FromDate AND 
OrderDate <= TransactionFeeProducts.ToDate AND 
TransactionFeeProducts.BatchID = 3
GROUP BY TransactionFeeProducts.ProductID, FromDate, ToDate 
ORDER BY SUM(Quantity) DESC

我希望SQL在TransactionFeeProducts中返回BatchID = 3的所有记录。 SUM(Quantity)应该只给我在TransactionFeeProducts.FromDate和TransactionFeeProducts.ToDate之间的OrderDate的总和

如果SUM(Quantity)为0,则该字段应为NULL或0。

我现在的问题是,如果SUM(Quantity)为0,则SQL不会返回任何记录。

请帮忙。非常感谢你。

2 个答案:

答案 0 :(得分:6)

将JOIN条件更改为

SELECT  SUM(Quantity) as Orders,  
        TransactionFeeProducts.ProductID, 
        FromDate, 
        ToDate  
FROM    TransactionFeeProducts LEFT JOIN 
        OrderProducts   ON  TransactionFeeProducts.ProductID = OrderProducts.ProductID 
                        AND OrderDate >= TransactionFeeProducts.FromDate 
                        AND OrderDate <= TransactionFeeProducts.ToDate 
WHERE   TransactionFeeProducts.BatchID = 3 
GROUP BY    TransactionFeeProducts.ProductID, 
            FromDate, 
            ToDate  
ORDER BY    SUM(Quantity) DESC

不同之处在于,如果将过滤条件放在WHERE子句中,它将影响查询过滤,就像使用INNER JOIN一样,说明您只包含来自TransactionFeeProducts其中OrderDate >= TransactionFeeProducts.FromDate and OrderDate <= TransactionFeeProducts.ToDate

看一下以下示例

DECLARE @TABLE1 TABLE(
        ID INT,
        FromDate DATETIME,
        ToDate DATETIME
)

INSERT INTO @TABLE1 SELECT 1, '01 Jan 2012','31 Jan 2012'

DECLARE @TABLE2 TABLE(
        ID INT,
        DateValue DATETIME
)

INSERT INTO @TABLE2 SELECT 1, '01 Feb 2012'

SELECT  *
FROM    @TABLE1 t1 LEFT JOIN
        @TABLE2 t2  ON  t1.ID = t2.ID
                    AND t2.DateValue BETWEEN t1.FromDate AND t1.ToDate

SELECT  *
FROM    @TABLE1 t1 LEFT JOIN
        @TABLE2 t2 ON   t1.ID = t2.ID
WHERE   t2.DateValue BETWEEN t1.FromDate AND t1.ToDate

选择1说:

返回T1中的所有行,仅返回来自t1.ID = t2.ID AND t2.DateValue BETWEEN t1.FromDate AND t1.ToDate

的T2的所有行

另一方面选择2说:

返回T1中的所有行,只返回来自T2 t1.ID = t2.ID的所有行,然后返回t2.DateValue BETWEEN t1.FromDate AND t1.ToDate

之前的行

SQL SERVER – Introduction to JOINs – Basic of JOINs总是很方便。

答案 1 :(得分:0)

我更喜欢astander的方法(在JOIN中过滤),但有时候有用的替代方法是在加入字段上添加一个OR IS NULL,例如。

WHERE
 TransactionFeeProducts.BatchID = 3
 AND
(OrderProducts.ProductID IS NULL
 OR 
(
   OrderDate >= TransactionFeeProducts.FromDate AND 
   OrderDate <= TransactionFeeProducts.ToDate 

))