当数据丢失时,在两个表之间合并

时间:2014-08-07 18:48:03

标签: sql sql-server-2008

朋友,我有查询根据信用卡表中的帐单邮寄地址ID的可用性从地址表中查找数据。问题是,对于信用卡表中的许多记录,账单地址id是全零的默认值。我想要做的是当账单地址id全为零时,对另一个默认地址表执行我的内连接。我相信解决方案是使用Coalesce。以下是查询。任何帮助将不胜感激。

select top 1
       u_address_id,
       u_address_name,
       ads.u_first_name,
       ads.u_last_name,
       ads.u_address_line1,
       ads.u_address_line2,
       u_city,
       u_region_code,
       u_postal_code,
       u_country_code,
       ads.u_tel_number,
       ads.u_tel_extension,
       uo.u_email_address,
       uo.u_user_id,
       pm.PaymentMethodName,
       ccea.CreditCard,
       ccea.u_id
from       CreditCard_Export_All ccea
inner join CreditCards           cc   on ccea.creditcard       = cc.u_id
inner join Addresses             ads  on cc.u_billing_address  = ads.u_address_id
inner join UserObject            uo   on ccea.UserId           = uo.u_user_id
inner join PaymentMethod         pm   on cc.u_payment_group_id = pm.GroupId
where ccea.CreditCard = @ccId
  and ccea.u_id between @_startUId and @_endUId
  and uo.u_email_address is not null
  and uo.u_email_address like @site+'_%'

2 个答案:

答案 0 :(得分:0)

不是这类问题的最佳解决方案,但它确实使用了合并。

select top 1
u_address_id,
u_address_name,
Coalesce(ads.u_first_name,ads2.u_first_name) as 'u_first_name',
Coalesce(ads.u_last_name,ads2.u_last_name) as 'u_last_name',
Coalesce(ads.u_address_line1,ads2.u_address_line1) as 'u_address_line1',
Coalesce(ads.u_address_line2,ads2.u_address_line2) as 'u_address_line2',
u_city, u_region_code,
u_postal_code,
u_country_code,
Coalesce(ads.u_tel_number,ads2.u_tel_number) as 'u_tel_number',
Coalesce(ads.u_tel_extension,ads2.u_tel_extension) as 'u_tel_extension',
uo.u_email_address,
uo.u_user_id,
pm.PaymentMethodName,
ccea.CreditCard,
ccea.u_id

from CreditCard_Export_All ccea
inner join CreditCards cc on ccea.creditcard = cc.u_id
left outer join Addresses ads on cc.u_billing_address = ads.u_address_id and ads.u_address_id != '000000000'
left outer join [ANOTHER DEFAULT ADDRESS TABLE] ads2 on cc.u_billing_address = ads2.u_address_id
inner join UserObject uo on ccea.UserId = uo.u_user_id
inner join PaymentMethod pm on cc.u_payment_group_id = pm.GroupId

where ccea.CreditCard = '" + ccId + "'" +
"and ccea.u_id between '" + _startUId + "' and '" + _endUId + "' " +
"and uo.u_email_address is not null " +
"and uo.u_email_address like '" + site + "_%'";

答案 1 :(得分:0)

为您提供的一些注意事项:

  • 您需要说top 1来控制结果集的大小,这是一种代码气味,表明您没有在SQL中提出正确的问题。

  • 始终使用表名别名限定列引用。它使您的SQL更容易阅读。而下一个必须了解它的人不必花时间试图找出哪个列来自哪个表。

  • 始终对表名称进行架构限定(dbo.some_table)。必须在每次调用时解析不受限制的名称:必须通过

    解析非限定对象引用
    • 探索当前会话的默认架构

    • 的命名空间
    • 如果未找到,则探测dbo命名空间。

    这会减慢计划编制,阻碍查询计划缓存,并可能导致创意,很难诊断错误,如果在当前会话'的默认模式拥有相同的名称(foo.some_table)的对象作为对象,你真的想要(dbo.some_table)。不要问我怎么知道这个。

  • 不要像你看起来那样构建SQL。它...

    • 向您展示SQL注入攻击

    • 阻止执行计划的缓存,因此需要在每次执行时重新编译/重新计划计划。请注意,这也会取决于依赖对象的编译锁定,这会导致瞬态阻塞和并发问题。

    • 打开你...当数据没有采用你认为的形式时,有趣的错误。

除此之外,这样的事情应该适合你:

select top 1
       address_id     = coalesce( ads.u_address_id    , soat.address_id       ) ,
       address_name   = coalesce( ads.u_address_name  , soat.address_name     ) ,
       first_name     = coalesce( ads.u_first_name    , soat.first_name       ) ,
       last_name      = coalesce( ads.u_last_name     , soat.last_name        ) ,
       addr_line_1    = coalesce( ads.u_address_line1 , soat.addr_line_1      ) ,
       addr_line_2    = coalesce( ads.u_address_line2 , soat.addr_line_2      ) ,
       city           = coalesce( ads.u_city          , soat.city             ) ,
       region_code    = coalesce( ads.u_region_code   , soat.region_code      ) ,
       postal_code    = coalesce( ads.u_postal_code   , soat.postal_code      ) ,
       country_code   = coalesce( ads.u_country_code  , soat.country_code     ) ,
       telephone      = coalesce( ads.u_tel_number    , soat.telephone_number ) ,
       telephone_ext  = coalesce( ads.u_tel_extension , soat.telephone_ext    ) ,
       email_address  = uo.u_email_address   ,
       user_id        = uo.u_user_id         ,
       payment_method = pm.PaymentMethodName ,
       credit_card    = ccea.CreditCard      ,
       credit_card_id = ccea.u_id
from      CreditCard_Export_All ccea
join      CreditCards           cc   on cc.u_id           = ccea.creditcard
join      UserObject            uo   on uo.u_user_id      = ccea.UserId
join      PaymentMethod         pm   on pm.GroupId        = cc.u_payment_group_id
left join Addresses             ads  on ads.u_address_id  = cc.u_billing_address
                                    and 0                != cc.u_billing_address
left join SomeOtherAddressTable soat on soat.address_id   = cc.some_other_address_id
                                    and 0                 = cc.u_billing_address
where ccea.CreditCard    =       @ccId
  and ccea.u_id          between @_startUId and @_endUId
  and uo.u_email_address is not  null
  and uo.u_email_address like    @site+'_%'

您可能还会考虑使用UNION,如下所示:

select address_id     = ads.u_address_id     ,
       address_name   = ads.u_address_name   ,
       first_name     = ads.u_first_name     ,
       last_name      = ads.u_last_name      ,
       addr_line_1    = ads.u_address_line1  ,
       addr_line_2    = ads.u_address_line2  ,
       city           = ads.u_city           ,
       region_code    = ads.u_region_code    ,
       postal_code    = ads.u_postal_code    ,
       country_code   = ads.u_country_code   ,
       telephone      = ads.u_tel_number     ,
       telephone_ext  = ads.u_tel_extension  ,
       email_address  = uo.u_email_address   ,
       user_id        = uo.u_user_id         ,
       payment_method = pm.PaymentMethodName ,
       credit_card    = ccea.CreditCard      ,
       credit_card_id = ccea.u_id
from CreditCard_Export_All ccea
join CreditCards           cc   on cc.u_id               = ccea.creditcard
                               and cc.u_billing_address != 0
join UserObject            uo   on uo.u_user_id          = ccea.UserId
join PaymentMethod         pm   on pm.GroupId            = cc.u_payment_group_id
join Addresses             ads  on ads.u_address_id      = cc.u_billing_address
where ccea.CreditCard    =       @ccId
  and ccea.u_id          between @_startUId and @_endUId
  and uo.u_email_address is not  null
  and uo.u_email_address like    @site+'_%'
UNION ALL
select address_id     = soat.address_id       ,
       address_name   = soat.address_name     ,
       first_name     = soat.first_name       ,
       last_name      = soat.last_name        ,
       addr_line_1    = soat.addr_line_1      ,
       addr_line_2    = soat.addr_line_2      ,
       city           = soat.city             ,
       region_code    = soat.region_code      ,
       postal_code    = soat.postal_code      ,
       country_code   = soat.country_code     ,
       telephone      = soat.telephone_number ,
       telephone_ext  = soat.telephone_ext    ,
       email_address  = uo.u_email_address    ,
       user_id        = uo.u_user_id          ,
       payment_method = pm.PaymentMethodName  ,
       credit_card    = ccea.CreditCard       ,
       credit_card_id = ccea.u_id
from CreditCard_Export_All ccea
join CreditCards           cc   on cc.u_id              = ccea.creditcard
                               and cc.u_billing_address = 0
join UserObject            uo   on uo.u_user_id         = ccea.UserId
join PaymentMethod         pm   on pm.GroupId           = cc.u_payment_group_id
left join SomeOtherAddressTable soat on soat.address_id = cc.some_other_address_id
                                    and 0               = cc.u_billing_address
where ccea.CreditCard    =       @ccId
  and ccea.u_id          between @_startUId and @_endUId
  and uo.u_email_address is not  null
  and uo.u_email_address like    @site+'_%'