2010-11-29 15 views
5

Bunu düşünemiyorum. Bu sorgu var: YeterinceBenzersiz olmayan çiftlerle SQL sorgusu yardımı

SELECT 
    p.person_id, 
    p.first_nm, 
    p.last_nm, 
    pu.purchase_dt, 
    pr.sku, 
    pr.description, 
    a.address_type_id, 
    a.city_cd, 
    a.state_cd, 
    a.postal_cd 
FROM 
    person p 
    INNER JOIN address a ON p.person_id = a.person_id 
    INNER JOIN purchase pu ON pu.person_id = p.person_id 
    INNER JOIN product pr ON pr.product_id = pu.product_id 

Basit - Sadece biz geri döner sevk ettik müşteriler için bilgi almak gerekir. Ancak, AddressType tablonun

AddressType 

address_type_id address_type_desc 
------------------------------------ 
1   Home 
2   Shipping 

bazı müşterilerin böyle benzersiz olmayan çift girişler oluşturarak adres tablosunda birden fazla adres, çünkü.

1,Smith, John, 12/01/2009, A12345, Purple Widget, 1, Anywhere, CA, 12345 
1,Smith, John, 12/01/2009, A12345, Purple Widget, 2, Somewhere, ID, 54321 
Ben sadece bir satır/kişi dönmek için sorgu almak ve aksi varsa ev adresini döndürür, teslimat adresi iade etmek istiyorum

.

Bu yeterince basit görünüyor ve belki de sadece benim soğuk, ama bu başımı biraz çizmeme neden oluyor.

+0

Hangi DB motoru? – Lex

+0

Ve kaç adres olabilir: 0., N, 1. N veya 1..2? – Lex

cevap

5
SELECT 
    p.person_id, 
    p.first_nm, 
    p.last_nm, 
    pu.purchase_dt, 
    pr.sku, 
    pr.description, 
    COALESCE(ha.address_type_id, sa.address_type_id) AS address_type_id 
    CASE WHEN ha.address_type_id IS NOT NULL THEN ha.city_cd ELSE sa.city_cd END AS city_cd, 
    CASE WHEN ha.address_type_id IS NOT NULL THEN ha.state_cd ELSE sa.state_cd END AS state_cd, 
    CASE WHEN ha.address_type_id IS NOT NULL THEN ha.postal_cd ELSE sa.postal_cd END AS postal_cd 
FROM 
    person p 
    LEFT JOIN address ha ON p.person_id = ha.person_id AND ha.address_type_id = 1 
    LEFT JOIN address sa ON p.person_id = sa.person_id AND sa.address_type_id = 2 
    INNER JOIN purchase pu ON pu.person_id = p.person_id 
    INNER JOIN product pr ON pr.product_id = pu.product_id 
6

yerine hepsini senin o min (AddressID) döndürür böylece katılmak değiştirmek istiyorum:

 INNER JOIN address a ON p.person_id = a.person_id 
     inner join (select person_id, min(address_type_id) as min_addr 
from address group by person_id) a_min 
on a.person_id = a_min.person_id and a.address_type_id = a_min.min_addr 
1

SQL Server veya ortak tablo ifadeleri ile diğer sürümü (CTE) Eğer seni aşağıdakileri yapabilirdi. CTE, kişi tarafından gruplandırılmış ve address_type_id tarafından sipariş edilen bir satır numarası sütunu ekler. Ana sorgu, CTE'den her bir kişi için 1 numaralı satırı döndürmek üzere değiştirilmiştir. Bu arada

WITH cte AS 
    (
    SELECT 
     a.person_id, 
     a.address_type_id, 
     a.city_cd, 
     a.state_cd, 
     a.postal_cd, 
     ROW_NUMBER() over (PARTITION BY person_id ORDER BY address_type_id) AS sequence 
    FROM address a 
    INNER JOIN AddressType at ON a.address_type_id = at.address_type_id 
    ) 

    SELECT 
     p.person_id, 
     p.first_nm, 
     p.last_nm, 
     pu.purchase_dt, 
     pr.sku, 
     pr.description, 
     a.address_type_id, 
     a.city_cd, 
     a.state_cd, 
     a.postal_cd 
    FROM 
     person p 
     INNER JOIN cte a ON p.person_id = a.person_id 
     INNER JOIN purchase pu ON pu.person_id = p.person_id 
     INNER JOIN product pr ON pr.product_id = pu.product_id 
    WHERE 
     a.sequence = 1 

, hiçbir adresleri kişi kayıtları varsa, (cevabım cte) adresleri masaya KATILIN İÇ bir dış etmek JOIN değiştirmek isteyebilirsiniz. Gereksinimleriniz belirtildiyse, bu satın alma ve ürüne katılım için de uygun olabilir.