TSQL选择一行或多行进行连接

时间:2012-04-24 10:33:17

标签: tsql sql-server-2005

这个问题类似于:TSQL select rows by one from 2 conditions,但我想要的结果有所不同

我有一张这样的表:

ORDER_ID   CODE1   CODE2   CODE3   STATUS    TYPE        SUM      GROUP
1          '001'   'BIGP'  NULL    4         'company'   120      48
2          '002'   'BIGP'  NULL    1         'priv'      100      20
3          '001'    NULL   NULL    6         'priv'      50       49
4          '002'    NULL   'L'     1         'company'   1253     22

和第二个表如下:

ADDRESS_ID   ORDER_ID   ZIP       TYPE   ADD_DATE       CATEGORY     VERIFIED
1            1          '15-125'    'K1'   '2010-01-01'   'CLIENT'     1
2            1          '22-022'    'D1'   '2010-01-02'   'SYSTEM'     1
3            2          '16-159'    'D2'   '2010-01-02'   'SYSTEM'     1
4            2          '15-125'    'D2'   '2010-02-01'   'CLIENT'     0

第三和第四张表包含邮政编码和城市名称,如下所示:

ZIP       CITY
'15-125'    'Warszawa'
'22-022'    'Koszalin'
'16-159'    'Krakow'
'15-125'    'Lublin'

对于每个订单

  • 状态不在(4,6)
  • 代码1介于'002'和'005'
  • 之间
  • (code2 = null和code3 = null)或(code2 in('BIGA','BIGP')and code3 = null)或(code2 = NULL and code3 ='L')

如果code1 ='002'和IN组(48,59,60,87),我必须选择一个地址
(非常感谢NikolaMarkovinović):

SELECT TOP 1000 o.order_Id
              , a.Address_Id
              , a.Zip
            --, *
FROM orders o
CROSS APPLY
(
 select TOP 1
        a.Address_Id,
        a.Zip
   from address a
  WHERE a.order_Id = o.order_Id
  ORDER BY case a.Type 
                when 'D2' then 1 
                when 'K1' then 2 
                else 3 
            end,
        a.ADD_DATE
) a
WHERE
 o.Status NOT IN (4, 6)
 AND code1='002'
 AND group IN (48,59,60,87)
 AND ((code2 IS NULL AND code3 IS NULL) OR (code2 IN ('BIGA', 'BIGP') AND code3 IS NULL) OR (code2 IS NULL AND code3 = 'L'))

对于所有符合最高标准且得到code1 ='002'IN组且NOT IN(48,59,60,87)的其他订单,我必须为那些已验证= 1的订单选择所有地址

收集这些地址后,我将能够检查特定邮政公司是否可以将邮件发送到这些地址(我将检查另一个包含邮政编码的表格)

我正在考虑使用union all,首先选择并与第二个进行联合,这将返回code1 ='002'和group NOT(48,59,60,87)的所有地址。

但也许没有工会可以做到这一点吗?

这是我想得到的最终结果:

CODE1        TYPE        COUNT_OF_ORDERS        COUNT_OF_ADDRESSES     COMPANY1  OTHER
'001'        'NORMAL'    125                    150                    110       40
'002'        'NORMAL'    100                    122                    100       22
'003'        'NORMAL'    150                    110                    100       10
'004'        'NORMAL'    200                    220                    220       0
'005'        'NORMAL'    220                    240                    210       30
'005'        'PRIORITY'  100                    110                    110       0
'SX1'        'PRIORITY'  100                    100                    20        80

因此,如果我的类型是“正常”,我必须检查订单中的地址是否存在于具有正常邮政编码的表中,如果它具有“优先级”类型,我必须在表格中检查优先级代码。

如果特定表格中存在代码,我会向COMPANY1列添加+1,如果不存在于OTHER,则这些列的总和必须是我的地址的总和。


这是我设法做的查询(在@NikolaMarkovinović的帮助下)

SELECT TOP 1000 o.order_Id
              , a.Address_Id
              , a.Zip
            --, *
FROM orders o
CROSS APPLY
(
 select TOP 1
        a.Address_Id,
        a.Zip
   from address a
  WHERE a.order_Id = o.order_Id
    AND code1='002'
    AND o.[group] IN (48,59,60,87)
  ORDER BY case a.Type 
                when 'D2' then 1 
                when 'K1' then 2 
                else 3 
            end,
        a.ADD_DATE
  UNION ALL
 select 
        a.Address_Id,
        a.Zip
   from address a
  WHERE a.order_Id = o.order_Id
    AND ((code1='002' AND o.[group] NOT IN (48,59,60,87)) OR code1 IN ('001', '003', '004', '005'))
    --I'm not shure of that top line, it work's but mayby it con de written better
    AND Verified = 1
) a
WHERE
 o.Status NOT IN (4, 6)
 AND ((code2 IS NULL AND code3 IS NULL) 
    OR (code2 IN ('BIGA', 'BIGP') AND code3 IS NULL) 
    OR (code2 IS NULL AND code3 = 'L'))

1 个答案:

答案 0 :(得分:1)

您可以轻松过滤地址([group] IN (48,59,60,87) OR Verified = 1),但调整TOP 1会让事情变得荒谬(TOP (case when [group] IN (48,59,60,87) then 1 else (select count(*) from addresses where order_Id = o.order_Id) end)。所以我建议您union all但只针对地址:

SELECT TOP 1000 o.order_Id
              , a.Address_Id
              , a.Zip
            --, *
FROM orders o
CROSS APPLY
(
 select TOP 1
        a.Address_Id,
        a.Zip
   from address a
  WHERE a.order_Id = o.order_Id
    AND o.[group] IN (48,59,60,87)
  ORDER BY case a.Type 
                when 'D2' then 1 
                when 'K1' then 2 
                else 3 
            end,
        a.ADD_DATE
  UNION ALL
 select 
        a.Address_Id,
        a.Zip
   from address a
  WHERE a.order_Id = o.order_Id
    AND o.[group] NOT IN (48,59,60,87)
    AND Verified = 1
) a
WHERE
 o.Status NOT IN (4, 6)
 AND code1='002'
 AND ((code2 IS NULL AND code3 IS NULL) 
    OR (code2 IN ('BIGA', 'BIGP') AND code3 IS NULL) 
    OR (code2 IS NULL AND code3 = 'L'))

P.S。如果订单可能没有地址,请用OUTER APPLY替换CROSS APPLY。