T-SQL查询根据具体情况加入不同的列

时间:2013-12-19 21:32:32

标签: sql tsql join

我有一个遗留系统,它有一个销售表和一个客户表,分别是CMS和CUST。我需要根据不同的标准查询发货地址。客户表将每个地址视为自己的客户。因此,如果我有一个帐单邮寄地址,那么一个送货地址,那些将是不同的CUSTNUM。 CMS表包含CUSTNUM和SHIPNUM列。如果销售订单使用帐单地址作为送货地址,则SHIPNUM = 0.如果这两个地址不同,则SHIPNUM =与CUSTNUM不同的客户编号。我正在尝试根据SHIPNUM的情况编写一个将CUST加入CMS的查询。 0或不。我的原始查询只使用了CUSTNUM,并忽略了SHIPNUM。我的新查询在语法上是正确的并且执行,但是对于旧查询,返回的行计数是2860对3590。旧的join语句只是注释掉的行:ON CMS.CUSTNUM = CUST.CUSTNUM。

from
        KGI_LOTNOS as LOT
        INNER JOIN CMS
                ON LOT.ORDERNO = CMS.ORDERNO
        JOIN CUST
                ON CUST.CUSTNUM = 
                        CASE
                                WHEN CMS.SHIPNUM > 0
                                        THEN CMS.SHIPNUM
                                Else CMS.CUSTNUM
                                END
--                ON CMS.CUSTNUM = CUST.CUSTNUM
        INNER JOIN COUNTRY as C
                ON CUST.COUNTRY = C.COUNTRY 

以下是CMS表中的示例;

CUSTNUM SHIPNUM ORDERNO
41863   77394   828509  <--Different billing and shipping address
43242   69291   776888  <--Different billing and shipping address
2356    0   765022  <--Same billing and shipping address

有关如何使这项工作的任何想法?

PS这是完整的原始查询。

select
        CUST.CUSTNUM as Customer,
        CMS.CUSTNUM,
        CMS.SHIPNUM,
        CUST.CTYPE,
        CMS.ORDERNO,
        CMS.ODR_DATE,
        LTRIM(RTRIM(CUST.FIRSTNAME)) as First,
        LTRIM(RTRIM(CUST.LASTNAME)) as Last,
        LTRIM(RTRIM(CUST.COMPANY)) as Company,
        LTRIM(RTRIM(CUST.PHONE)) as Phone,
        LTRIM(RTRIM(CUST.EMAIL)) as Email,
        LTRIM(RTRIM(CUST.ADDR)) as ADDR1,
        LTRIM(RTRIM(CUST.ADDR2)) as ADDR2,
        LTRIM(RTRIM(CUST.ADDR3)) as ADDR3,
        LTRIM(RTRIM(CUST.CITY)) as City,
        LTRIM(RTRIM(CUST.State)) as State,
        LTRIM(RTRIM(CUST.ZIPCODE)) as Zip,
        LTRIM(RTRIM(C.NAME)) as Country,
        LOT.ITEMNO,
        LOT.LOTNO,
        COUNT(LOT.ITEMNO) as Quantity
from
KGI_LOTNOS as LOT
INNER JOIN CMS
   ON LOT.ORDERNO = CMS.ORDERNO
LEFT JOIN CUST
   ON CMS.CUSTNUM = CUST.CUSTNUM
INNER JOIN COUNTRY as C
   ON CUST.COUNTRY = C.COUNTRY 
where
          (
               CUST.CTYPE IN ('P','W','Z')
          )
        AND
                (
                        LOT.LOTNO IN ('1000001','20001','300001')
                )
GROUP BY 
        CMS.ORDERNO,
        CUST.CUSTNUM,
        CMS.CUSTNUM,
        CMS.SHIPNUM,
        CUST.CTYPE,
        CUST.FIRSTNAME,
        CMS.ODR_DATE,
        CUST.LASTNAME,
        CUST.COMPANY,
        CUST.PHONE,
        CUST.EMAIL,
        CUST.ADDR,
        CUST.ADDR2,
        CUST.ADDR3,
        LOT.ITEMNO,
        CUST.CITY,
        CUST.STATE,
        CUST.ZIPCODE,
        C.NAME,
        LOT.LOTNO
ORDER BY
        Customer,
        CMS.ORDERNO,
        LOT.ITEMNO,
        LOT.LOTNO

4 个答案:

答案 0 :(得分:1)

如果您使用INNER JOIN,则有可能排除在另一个表中没有引用的原始数据。这可能是由表达式中的另外两个连接中的任何一个引起的 - 评论它们并再试一次。如果您仍然收到较少的记录,则应检查数据的一致性 - 一个表的值与另一个表中的值不对应。

顺便说一句,我不喜欢CASE表达式中的JOIN因为它看起来很难看。你对这个似乎也在做这个表达的表达方式有什么看法:

 LEFT JOIN CUST
      ON CUST.CUSTNUM = COALESCE(NULLIF(CMS.SHIPNUM, 0), CMS.CUSTNUM)

答案 1 :(得分:0)

使用更改的条件加入的记录越少,CMS.SHIPNUM表中的某些CUSTNUM值与CUST不匹配。

要查找有问题的条目,请从INNER更改为OUTER加入并添加WHERE条件,例如:

  LEFT JOIN CUST
      ON CUST.CUSTNUM =  CASE  WHEN CMS.SHIPNUM > 0 THEN CMS.SHIPNUM
                               ELSE CMS.CUSTNUM
                         END
  WHERE CUST.CUSTNUM IS NULL
      AND CMS.SHIPNUM > 0

修改:您必须将INNER JOIN移至COUNTRY才能看到与更新后的JOIN无法匹配,因为它加入了来自客户表的字段,并确保在SHIPNUM中有SELECT字段。

答案 2 :(得分:0)

您可以使用这样的CTE。

WITH cte(ORDERNO,SHIPNUM)AS (   SELECT ORDERNUM,SHIPNUM = CASE 什么时候CMS.SHIPNUM&gt; 0

FROM CMS

答案 3 :(得分:0)

您的查询看起来正确但不确定为什么它不起作用,请尝试在发货时将joinCUST表保留两次,另一次在结算时保留,然后为每个客户列写下case语句。

select
 LTRIM(RTRIM(case when CMS.SHIPNUM > 0 THEN CUST.FIRSTNAME else CUST_BILL.FIRSTNAME end  )) as First,
from
    KGI_LOTNOS as LOT
    INNER JOIN CMS
            ON LOT.ORDERNO = CMS.ORDERNO
    left JOIN CUST CUST
            ON CUST.CUSTNUM = CMS.SHIPNUM 
     left JOIN CUST CUST_BILL      
          ON CMS.CUSTNUM = CUST_BILL.CUSTNUM
    INNER JOIN COUNTRY as C
            ON CUST.COUNTRY = C.COUNTRY 

如果它仍然输出较少的行,则其他错误