【问题标题】:Alternate of except in sql在 sql 中替代 except
【发布时间】:2019-11-13 11:15:22
【问题描述】:

我想使用except的替代。我使用了左连接,但它没有带来所需的列数据。

SELECT ACCOUNT_NO, BILL_CYCLE_DATE, 2 FROM CSS_BILL_Job 
WHERE (BILL_CYCLE_DATE = 20190526 OR  BILL_CYCLE_DATE = 20190525) --33612
EXCEPT
SELECT DISTINCT ACCOUNT_NO, BILL_CYCLE_DATE, 2  FROM TempNotRunResults --33505

但是现在当我使用 LEFT JOIN 时。

SELECT A.ACCOUNT_NO, A.BILL_CYCLE_DATE, B.DATE_BILLED,
B.DATE_PAYMENT_DUE,B.TOTAL_BILL_AMT, B.LPC_AMT, B.BILL_FREQ, B.BILL_CYCLE_TYPE
FROM CSS_BILL_Job A LEFT JOIN TempNotRunResults B
ON A.ACCOUNT_NO  = B.ACCOUNT_NO
WHERE (A.BILL_CYCLE_DATE = 20190526 OR  A.BILL_CYCLE_DATE = 20190525)
AND A.ACCOUNT_NO NOT IN ( SELECT ACCOUNT_NO FROM TempNotRunResults)

我看到 B.DATE_PAYMENT_DUE、B.TOTAL_BILL_AMT、B.LPC_AMT、B.BILL_FREQ、B.BILL_CYCLE_TYPE 为 NULLS,这是不对的。如何在左连接查询中填充表 B 中的列?

【问题讨论】:

  • 你为什么使用左连接?
  • 发布一些示例数据和您想要的输出。
  • 解释“除外的替代”。 PS 用于计算除了做什么的左连接习语是一个常见问题解答。 PSminimal reproducible example
  • @nick 你接受和不接受我的回答了吗?

标签: sql-server left-join except


【解决方案1】:

似乎您不太了解 EXCEPT 的作用。它从第一个结果集中返回与第二个结果集中的任何内容都不匹配的不同行。请注意,使用 distinct 生成第二个结果集没有有用的效果。

要使用联接获得等效结果,您需要进行外部联接(就像您所做的那样),但要测试未保留的表中是否不存在行 (TempNotRunResults)。就像这样:

set nocount on;

declare @bill table (account_no tinyint, bill_cycle  date);
insert @bill (account_no, bill_cycle) values 
(1, '20190531'), 
(1, '20190430'), 
(2, '20190215'), 
(1, '20190531'); -- notice the duplicate for <1, May 31>

declare @notrun table (account_no tinyint, bill_cycle date);
insert @notrun (account_no, bill_cycle) values 
(1, '20190430'), 
(1, '20190630'), 
(1, '20190430'); -- notice the duplicate for <1, Apr 30>

select account_no, bill_cycle from @bill 
except 
select account_no, bill_cycle from @notrun
;

select bl.account_no, bl.bill_cycle 
from @bill as bl left join @notrun as nr 
on bl.account_no = nr.account_no 
and bl.bill_cycle = nr.bill_cycle
where nr.account_no is null
order by bl.account_no, bl.bill_cycle ;

请注意加入版本中的重复项。 EXCEPT 删除重复项。而且由于 EXCEPT 告诉我们在 TempNotRunResults 中没有匹配项,因此在加入时尝试包含该表中的列是没有意义的 - 很简单,除了 NULL 之外没有任何内容。但是,您确实在加入版本中单独加入了 ACCOUNT_NO。这是非常不同的逻辑,因此很难知道您到底要完成什么。这让我们回到了 Han 的请求——发布示例数据和您的预期结果。

【讨论】:

    【解决方案2】:

    如果您不希望表 TempNotRunResults 中出现空值,请使用此连接:

    SELECT A.ACCOUNT_NO, A.BILL_CYCLE_DATE, B.DATE_BILLED,
    B.DATE_PAYMENT_DUE,B.TOTAL_BILL_AMT, B.LPC_AMT, B.BILL_FREQ, B.BILL_CYCLE_TYPE
    FROM CSS_BILL_Job A LEFT JOIN TempNotRunResults B
    ON A.ACCOUNT_NO = B.ACCOUNT_NO 
    WHERE 
      (A.BILL_CYCLE_DATE = 20190526 OR  A.BILL_CYCLE_DATE = 20190525)
      AND 
      B.ACCOUNT_NO IS NOT NULL
    

    条件B.ACCOUNT_NO IS NOT NULL 仅获取匹配的行,这也可以通过使用INNER 连接来完成:

    SELECT A.ACCOUNT_NO, A.BILL_CYCLE_DATE, B.DATE_BILLED,
    B.DATE_PAYMENT_DUE,B.TOTAL_BILL_AMT, B.LPC_AMT, B.BILL_FREQ, B.BILL_CYCLE_TYPE
    FROM CSS_BILL_Job A INNER JOIN TempNotRunResults B
    ON A.ACCOUNT_NO = B.ACCOUNT_NO
    WHERE (A.BILL_CYCLE_DATE = 20190526 OR  A.BILL_CYCLE_DATE = 20190525)
    


    但是您的问题的标题是:“Alternate of except in sql”,这与您所说的要实现的目标相反:从表中填充列B 在我的左连接查询中,因为如果您想从表 B 中填充行,那么您需要匹配的行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-16
      • 2018-04-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多