3

これは次のような質問です: 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

そして2番目のテーブルは次のようになります:

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

3 番目と 4 番目のテーブルには、次のような郵便番号と都市名が含まれています。

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

すべての注文について

  • (4,6) にないステータス
  • '002' と '005' の間のコード 1
  • (code2=null and code3=null) or (code2 in ('BIGA', 'BIGP') and code3=null) or (code2=NULL and code3 = 'L')

code1 ='002' AND group IN (48,59,60,87) の場合、単一のアドレスを選択する必要があります
(Nikola Markovinović に感謝します):

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' AND group NOT IN (48,59,60,87) を取得した他のすべての注文については、検証済み = 1 の注文のすべての住所を選択する必要があります

これらの住所を収集した後、特定の郵便会社が私のメールをそれらの住所に配達できるかどうかを確認できます (郵便番号を含む別の表で確認します)。

最初の選択を取り、コード1 = '002' ANDグループNOT IN(48,59,60,87)のすべてのアドレスを返す2番目のユニオンを作成して、ユニオンをすべて作成することを考えていました。

しかし、ユニオンオールなしでそれを行うことは可能でしょうか?

これが私が得たい最終結果です:

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 に追加しない場合は、それらの列の合計が私のアドレスの合計になるようにします。


これは私がなんとかしたクエリです(@Nikola Markovinovićの助けを借りて)

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'))
4

1 に答える 1

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'))

PS 注文に住所がない可能性がある場合は、CROSS APPLY を OUTER APPLY に置き換えてください。

于 2012-04-24T15:05:07.547 に答える