2010-06-28 14 views
5

Aşağıdaki gibi görünen bir veri kümem var.Her çalışan için sırasız alanı kriterler olarak tam olarak bir satır seçin

EMPLID PHONE_TYPE PHONE 
------ ---------- -------- 
100  HOME  111-1111 
100  WORK  222-2222 
101  HOME  333-3333 
102  WORK  444-4444 
103  OTHER  555-5555 

Ben tercihlerini kurmak için PHONE_TYPE alanını kullanarak her bir çalışan için tam bir satır seçmek istiyor. Çalışan numarası 100 ve 101 için olduğu gibi çalışanı varsa EV numarasını istiyorum. EV numarası mevcut değilse, İŞ numarasını (çalışan 102) istiyorum ve son çare olarak çalışanın 103 olduğu rakam. Gerçekte benim masamın PHONE_TYPE alanı için yaklaşık bir düzine değeri var, bu yüzden örnekte gösterdiğim üç değerden fazlasını içerecek şekilde herhangi bir çözümü genişletmem gerekiyor. Düşüncesi olan var mı? Teşekkürler.

+0

Yani, her bir Çalışan Kimliği için telefon türüne göre kayıt tercihiyle bir kayıt mı istiyorsunuz? –

+0

Bu doğru.Tablo, her çalışan için bir EV telefonuna sahip olduğu garanti edilmez, ancak bir şey seçmem gerekiyor ve rastgele bir değer elde etmek için basit bir TOP (1) kullanmak istemiyorum. Esasen, ikinci bir seçim, 3. seçim, vb. Olmak istiyorum. – SteveM82

+1

Tercih tablosunda bir telefon defterinde saklanan tüm telefon tiplerine sahip misiniz? –

cevap

2

Unutmayın, Server 2000 Coalesce'i destekliyor mu? Eğer varsa, bu işe yarayacak: Bir çalışanın belirli bir telefon türü için birden fazla telefon numarasına sahip izin verilmesi halinde

Select Distinct EmplID, Coalesce(
    (Select Phone from Employees where emplid = e1.emplid and phone_type = 'HOME'), 
    (Select Phone from Employees where emplid = e1.emplid and phone_type = 'WORK'), 
    (Select Phone from Employees where emplid = e1.emplid and phone_type = 'OTHER') 
) as Phone 
From Employees e1 
+0

Şaşırtıcı bir şekilde, evet, SQL Server 2000 Coalesce'i destekler. Yeni PHONE_TYPE değerlerinin eklenmesi durumunda kodun düzenlenmesinin gerekmesine rağmen, bunun işe yarayacağını düşünüyorum (olası değil, ancak mümkün). Teşekkürler. – SteveM82

+0

Kesinlikle haklısınız. Diğer cevapta, fazladan bir tablo kullanan yaklaşımın aynı olması gerekir. Yeni bir telefon türü eklediyseniz, yardımcı tablonuza girişler eklemeniz gerekir. Daha iyi bir yaklaşım, ekstra tablolar ekleyip ekleyemeyeceğinize bağlıdır. –

+0

Bu yaklaşım, yeni bir telefon türü eklendiğinde veya ilgili öncelik değiştiğinde program kodunda değişiklikler yapılmasını gerektirir. Diğer çözüm sadece düzenleme verilerini gerektirir. Bir istisna, bu çözümü bir görünümde kapsıyor olmanızdır. Ancak, SQL Server sonuçları döndüren biriyle karşılaştığında SELECTleri değerlendirmeyi durdurup durmayacağını biliyor musunuz? Ya da tüm SELECTs değerlendirmesi ve daha sonra COALESCE uygulandı mı? –

3

Bir phone_types tablosu eklemeniz gerekir (Phone_Type TEXT (Whatever), Priority INTEGER). Bu tabloda, her bir Phone_Type değerini bir kez listeleyin ve ona bir öncelik atayınız (örneğinizde, HOME 1, WORK 2, OTHER 3 vb.). Daha sonra, Öncelik sütununa Phone_Types'den Phone_Numbers tablosuna katılan bir görünüm oluşturun (buna Phone_Numbers_Ex adını verdiğimizi hayal edin). ,

SELECT * FROM Phone_Numbers_Ex P1 WHERE NOT EXISTS 
    (SELECT * FROM Phone_Numbers_Ex P2 WHERE P2.EmplID = P1.EmplID AND P2.Priority < P1.Priority) 

başka yolu da başka bir görünüm beyan etmektir:

Şimdi, muhtemelen en net olan belirli bir emplID için MIN (Öncelik) ile Phone_Numbers_Ex Kaydı nasıl için birkaç seçeneğiniz vardır veya iç sorgu, SELECT EmplID, MIN(Priority) AS Priority FROM Phone_Numbers_Ex GROUP BY EmplID satırları boyunca ve daha sonra bu Emploid ve Öncelikli olarak bu arka Telefon_Numbers_Ex katılarak.

+0

Larry, girişiniz için teşekkürler. Sağlanan g.d.d.c, PHONE_TYPE değerlerinin değişme olasılığının düşük olması nedeniyle iyi çalışıyor. Çözümünüzün yaptığı gibi bir tabloya satır eklemenin, PHONE_TYPE değerlerinin değişme olasılığı daha yüksek olduğunda kodu değiştirmekten daha iyi olduğunu kabul ediyorum. Artı, yeni bir işlev öğrendim - birleşme. – SteveM82

0

Talepleriniz tam olmayabilir. Sadece bir şeyi benzersiz hale getirmek için bir telefon_number_id ekledim ve eğer kişi aynı türden iki telefona sahipse en düşük kimliği isteyeceğinizi varsayalım. Bu oldukça keyfi, ancak kendi iş mantığınız ile değiştirebilirsiniz.

Ayrıca, hangi telefon numarasının kullanılmasının önceliğini içeren bir tür Phone_Types tablosu da aldım. Bu tabloya sahip değilseniz, muhtemelen eklemelisiniz. Başka bir şey yoksa, telefon türlerini yabancı bir tuşla kısıtlamanıza izin verir. NOT EXISTS ait Ayrıca SOL bunu uygulamak

SELECT 
    PN1.employee_id, 
    PN1.phone_type, 
    PN1.phone_number 
FROM 
    Phone_Numbers PN1 
INNER JOIN Phone_Types PT1 ON 
    PT1.phone_type = PN1.phone_type 
WHERE 
    NOT EXISTS 
    (
     SELECT * 
     FROM 
      Phone_Numbers PN2 
     INNER JOIN Phone_Types PT2 ON 
      PT2.phone_type = PN2.phone_type AND 
      (
       (PT2.priority < PT1.priority) 
--OR (PT2.priority = PT1.priority AND PN2.phone_number_id > PN1.phone_number_id) 
      ) 
    ) 

yerine JOIN veya tek bir çalışan için telefon numarasını arayacak olsanız TOP kullanabilirsiniz. Sadece bir öncelikli BY 1 ORDER BY önceliği, telefon_numara_id.

Son olarak, SQL 2005 veya SQL 2008'e kadar hareket edecekseniz, ROWNUMBER() OVER (öncelik sırası, telefon_numarası, PARTITION BY employee_id) < ile bir CTE kullanabilirsiniz - sözdizimi biraz kapalı olabilir Bunun üzerinde parantez ile, ama umarım yeterince açık. Bu, ROWNUMBER() = 1.

+0

PHONE_TYPE alanı, uygulamamın tablosundaki bir anahtardır, bu nedenle belirli bir tür için birden fazla telefon numarasına sahip olmak mümkün değildir. Teşekkürler. – SteveM82

+0

Bu biraz daha kolay. Gereksiz kodu açıklayacağım ama yine de başkalarının referansları için orada bırakacağım. –

0

öğesini seçerek tüm çalışanlar için en iyi olanı seçmenize izin verir. Sol yan ekler kullanabileceğiniz Select yan tümcesinde sorgular kullanan bir g.d.d.c'nin yanıtı olarak. Daha iyi bir performans elde edebilirsin, ama elbette test etmelisin.

SELECT 
    e1.iD, 
    Coalesce(phoneHome.Phone,phoneWork.Phone,phoneOther) phone 
FROm 
    employees e1 
    LEFT JOIN phone phoneHome 
    ON e1.emplId = phoneHome 
     and phone_type = 'HOME' 
    LEFT JOIN phone phoneWork 
    ON e1.emplId = phoneWork 
     and phone_type = 'WORK' 
    LEFT JOIN phone phoneWork 
    ON e1.emplId = phoneOTHER 
     and phone_type = 'OTHER'