左边加入COALESCE的结果

时间:2018-04-30 09:14:40

标签: sql sql-server left-join coalesce

    SELECT  *
      FROM  TBDA temp
 LEFT JOIN (
            SELECT
            (
              COALESCE (
                 (
                    SELECT sum_payment
                      FROM TBDA_REPAYMENT 
                     WHERE isdn = temp.isdn
                       AND tr_month = temp.tr_month
                       AND tr_year = temp.tr_year 
                ),
                 (
                    SELECT sum_payment
                      FROM TBDA_PAYNEW 
                     WHERE isdn = temp.isdn
                       AND tr_month = temp.tr_month
                       AND tr_year = temp.tr_year 
                )
              )
            )
          )
  
      
  • TBDA表有isdn,tr_month,tr_year
  •   
  • TBDA_REPAYMENT表有isdn,tr_month,tr_year,sum_payment
  •   
  • TBDA_PAYNEW表有isdn,tr_month,tr_year,sum_payment
  •   

预期结果:

使用sum_payment关闭所有TBDA字段的表,通过比较isdn,tr_month,tr_year,如果sum_payment存在于两个表中的一个表中,则通过ISDN(TBDA表)从两个表(TBDA_REPAYMENT& TBDA_PAYNEW)中查找sum_payment(TBDA_REPAYMENT& ; TBDA_PAYNEW)然后将其添加到结果中,否则它为空。

我收到错误:

  

[Err] 42000 - [SQL Server]')'附近的语法不正确。

4 个答案:

答案 0 :(得分:1)

SELECT
    *
FROM
    TBDA temp
Cross Apply (   SELECT  COALESCE (
                        (
                            SELECT
                                sum_payment
                            FROM
                                TBDA_REPAYMENT 
                            WHERE
                                isdn = temp.isdn
                            AND tr_month = temp.tr_month
                            AND tr_year = temp.tr_year 
                        ),
                        (
                            SELECT
                                sum_payment
                            FROM
                                TBDA_PAYNEW 
                            WHERE
                                isdn = temp.isdn
                            AND tr_month = temp.tr_month
                            AND tr_year = temp.tr_year 
                        )   
                    ) as First_Null_Value

            ) as value_table

答案 1 :(得分:1)

除非使用CROSS JOIN,CROSS APPLY或OUTER APPLY,否则需要ON条款 因此错误。
虽然您仍然可以执行... LEFT JOIN othertable ON (1=1)

之类的操作

但您可以使用2个左连接重写此查询。

select 
 temp.*,
 coalesce(repay.sum_payment, paynew.sum_payment) as value_table
from TBDA temp
left join TBDA_REPAYMENT repay on (repay.isdn = temp.isdn and repay.tr_month = temp.tr_month and repay.tr_year = temp.tr_year)
left join TBDA_PAYNEW paynew on (paynew.isdn = temp.isdn and paynew.tr_month = temp.tr_month and paynew.tr_year = temp.tr_year);

请注意,假设表TBDA_REPAYMENT& TBDA_PAYNEW在连接中使用的3个字段(isdn,tr_month,tr_year)具有唯一性。

或者可以使用OUTER APPLY语法。 如果(isdn,tr_month,tr_year)没有唯一性,那么你可以使用它来同时计算总数。

select 
 temp.*, repay.sum_payment as repay_sum_payment, paynew.sum_payment as  paynew_sum_payment,
 coalesce(repay.sum_payment, paynew.sum_payment) as value_table
from TBDA temp
outer apply
(
  select nullif(sum(rp.sum_payment),0) as sum_payment
  from TBDA_REPAYMENT rp 
  where rp.isdn = temp.isdn 
    and rp.tr_month = temp.tr_month 
    and rp.tr_year = temp.tr_year
) as repay
outer apply 
(
  select nullif(sum(pn.sum_payment),0) as sum_payment
  from TBDA_PAYNEW pn 
  where pn.isdn = temp.isdn 
    and pn.tr_month = temp.tr_month 
    and pn.tr_year = temp.tr_year
) as paynew;

示例代码段

declare @TBDA table (isdn int, tr_month int, tr_year int);
declare @TBDA_REPAYMENT table (isdn int, tr_month int, tr_year int, sum_payment int);
declare @TBDA_PAYNEW  table (isdn int, tr_month int, tr_year int, sum_payment int);

insert into @TBDA (isdn, tr_month, tr_year) values (1,6,2018),(2,6,2018);
insert into @TBDA_REPAYMENT (isdn, tr_month, tr_year, sum_payment) values (1,6,2018, 100);
insert into @TBDA_PAYNEW (isdn, tr_month, tr_year, sum_payment) values (1,6,2018, 200),(2,6,2018,100),(2,6,2018,200);

--
-- Using left join
--
select 
 temp.*, repay.sum_payment, paynew.sum_payment,
 coalesce(repay.sum_payment, paynew.sum_payment) as value_table
from @TBDA temp
left join @TBDA_REPAYMENT repay on (repay.isdn = temp.isdn and repay.tr_month = temp.tr_month and repay.tr_year = temp.tr_year)
left join @TBDA_PAYNEW paynew on (paynew.isdn = temp.isdn and paynew.tr_month = temp.tr_month and paynew.tr_year = temp.tr_year);

--
-- Using outer apply
--
select 
 temp.*, repay.sum_payment as repay_sum_payment, paynew.sum_payment as  paynew_sum_payment,
 coalesce(repay.sum_payment, paynew.sum_payment) as value_table
from @TBDA temp
outer apply
(
  select nullif(sum(rp.sum_payment),0) as sum_payment
  from @TBDA_REPAYMENT rp 
  where rp.isdn = temp.isdn 
    and rp.tr_month = temp.tr_month 
    and rp.tr_year = temp.tr_year
) as repay
outer apply 
(
  select nullif(sum(pn.sum_payment),0) as sum_payment
  from @TBDA_PAYNEW pn 
  where pn.isdn = temp.isdn 
    and pn.tr_month = temp.tr_month 
    and pn.tr_year = temp.tr_year
) as paynew;

答案 2 :(得分:0)

错误是由于未在ON上指定LEFT JOIN条件。

没有LEFT JOIN

ON会抛出错误。

如果您不想指定任何条件,请尝试CROSS JOIN

答案 3 :(得分:0)

只需使用相关子查询:

SELECT t.*,
       IFNULL (  (SELECT r.sum_payment
                   FROM TBDA_REPAYMENT r
                   WHERE r.isdn = t.isdn AND
                         r.tr_month = t.tr_month AND
                         r.tr_year = t.tr_year 
                  ),
                  (SELECT p.sum_payment
                   FROM TBDA_PAYNEW p
                   WHERE p.isdn = t.isdn AND
                         p.tr_month = t.tr_month AND
                         p.tr_year = t.tr_year 
                  )
               )
        )
FROM TBDA t;

尽管您可以使用APPLY,但使用SELECT已经坚持要从子查询中返回最多一行。

还要注意几件事。首先,我将COALESCE()替换为IFNULL()。虽然我更喜欢COALESCE()(因为它是标准且更灵活),但使用IFNULL()代码效率更高。 COALESCE()会导致SQL Server在第一个参数不是NULL时对其进行两次计算。

其次,应在查询中的任何位置使用表别名和限定列名。