T-SQL中的条件逻辑选择语句

时间:2017-10-18 04:52:28

标签: sql-server tsql

在SQL Server 2014的数据库中,我有一个CustomerRecords表,其中包含地址列AddressCityStateZip

我还有一个CustomerBillingAddresses表,与CustomerRecordsCustomerID的FK关系。此表还包含Address, City, State, Zip列,但另外还有Active(位)列。每个CustomerID只能有一个活动记录。

并非所有CustomerRecords都位于CustomerBillingAddresses,并且CustomerBillingAddresses中的所有记录都不是有效的Active=1

我想要返回这样的客户信息:

CustomerID, Name, Address, City, State, Zip

但是如果CBA中的CustomerRecords位为真,我只想从CustomerBillingAddressesActive返回一组地址信息。

到目前为止,我有这个:

SELECT DISTINCT 
    cr.CustomerID, cr.CustomerName,
    CASE  
       WHEN cba.CustomerID IS NOT NULL
          THEN cba.Address
          ELSE cr.Address
       END AS Address,
    CASE 
       WHEN cba.CustomerID IS NOT NULL
          THEN cba.City
          ELSE cr.City
       END AS City, 
    CASE 
       WHEN cba.CustomerID IS NOT NULL
          THEN cba.State
          ELSE cr.State
    END AS State, 
    CASE 
       WHEN cba.CustomerID IS NOT NULL
          THEN cba.Zip
          ELSE cr.Zip
    END AS Zip
FROM
    dbo.CustomerRecords cr
LEFT JOIN 
    dbo.CustomerBillingAddresses cba ON cba.CustomerID = cr.CustomerID
                                     AND cba.Active = 1

当找到活动的CBA地址时,我无法排除CR地址,因为它们附加到基本记录CustomerID。我意识到这是糟糕的数据库形式,但它是我必须使用的。此外,规范化不会像这样有趣,对吗?

问题

我的查询实际上得到了我想要的结果,并且似乎没有比原始查询更糟糕的表现,但我确信有更好的方法。

我一遍又一遍地重复看到“cba.CustomerID IS NOT NULL”的情况......

我提前感谢任何帮助,建议或解答。

3 个答案:

答案 0 :(得分:0)

您的查询给人的印象是,如果某行的cba.CustomerID为NULL,则该行的每个其他字段都将为空,应该被忽略。

在这种情况下,您可以使用COALESCE表达式。

  

COALESCE expression returns the first non-null expression in the list to be evaluated.

   SELECT DISTINCT cr.CustomerID, cr.CustomerName, COALESCE(cba.Address, 
   cr.Address) AS Address, 
   COALESCE(cba.City, cr.City) AS City, COALESCE(cba.State, cr.State) AS State, 
   COALESCE(cba.Zip, cr.Zip) AS Zip
    FROM dbo.CustomerRecords cr
    LEFT JOIN dbo.CustomerBillingAddresses cba ON cba.CustomerID = cr.CustomerID
        AND cba.Active = 1

或者你可以简单地使用ISNULL函数。

  

ISNULL replaces NULL with the specified replacement value.

SELECT DISTINCT cr.CustomerID, cr.CustomerName, ISNULL(cba.Address, 
       cr.Address) AS Address, 
       ISNULL(cba.City, cr.City) AS City, ISNULL(cba.State, cr.State) AS State, 
       ISNULL(cba.Zip, cr.Zip) AS Zip
        FROM dbo.CustomerRecords cr
        LEFT JOIN dbo.CustomerBillingAddresses cba ON cba.CustomerID = cr.CustomerID
            AND cba.Active = 1

答案 1 :(得分:0)

如果dbo.CustomerBillingAddresses不可为空,则当cba.CustomId为null时,cba.Address为NULL。所以你可以直接检查cba.Address。

SELECT DISTINCT cr.CustomerID, cr.CustomerName,
COALESCE(cba.Address, cr.Address) AS Address
...other columns
FROM dbo.CustomerRecords cr
    LEFT JOIN dbo.CustomerBillingAddresses cba ON cba.CustomerID = cr.CustomerID
        AND cba.Active = 1

答案 2 :(得分:0)

我有办法解决这个问题,但它可能仍然会让你感到畏缩,我也不知道这个表现。

方式只是union - 2个查询,第一个用于Active = 0,第二个用于Active = 1.您只需要从相应的列获取。无需case whencoalesce

例如:

select t1.address, t1.city from table1 t1 where t1.active = 0
union
select t2.address, t2.city from table1 t1 
    inner join table2 t2 on t1.customer = t2.customer where t1.active = 1