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

Sql 数据丢失时在两个表之间合并,sql,sql-server-2008,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,

朋友们,我有一个查询,它根据信用卡表中账单地址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+'_%'

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

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 + "_%'";
请注意:

  • 要控制结果集的大小,您需要说
    top 1
    ,这是一种代码气味,表明您在SQL中问的问题不对

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

  • 始终使用模式限定表名(
    dbo.some\u表
    )。每次调用都必须解析非限定名称:非限定对象引用必须由

    • 探测当前会话的默认架构的命名空间

    • 如果未找到,则探测
      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+'_%'
您还可以考虑使用一个联合体,例如:

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+'_%'

也许您可以将问题简化为两到三个表,并提供示例数据和所需结果。这将使您更容易理解需要做什么。合并将不会帮助您,因为它只允许您消除空值,而不是默认值。如果要获取的值不是全零,可以使用CASE语句。
其他默认地址表
只有一行,其中u\u address\u id为全零?现在还不清楚。请发布一些数据。非常感谢您的反馈。