2013-07-06 34 views
6

ardışık numaraları eksik buluyorum.SQL sorgusu bir SQL Tablo Aşağıdaki veriler var

Örneğin, ben kimlikleri sırayla eksik Çalışan 1021 için almalısınız: 2 ve 5 ile Çalışan 1027 için almalısınız eksik sayılar 1 ve 6

o sorgulamak konusunda herhangi bir ipucu?

Herhangi bir yardımı için teşekkür ederiz.

+0

tam sütun isimlerini göremiyoruz – Hogan

+1

Son sütun adı "familyid". – VAAA

+0

ve 3. sütun ve tablo adı? – Hogan

cevap

3

ilk eksik değerini

I bul "Doğru" sıra kimlik numarası atamak için ROW_NUMBERwindow function kullanır. dizisi kimlik her zaman çalışan kimliği değişiklikleri yeniden varsayarsak: Sonra

SELECT 
    e.id, 
    e.name, 
    e.employee_number, 
    e.relation, 
    e.familyid, 
    ROW_NUMBER() OVER(PARTITION BY e.employeeid ORDER BY familyid) - 1 AS sequenceid 
FROM employee_members e 

, ben sadece ayarlı Sonuca filtre olur uyuşmazlık dizisi kimlikleri ile satırları şunlardır: Sonra tekrar

SELECT * 
FROM (
    SELECT 
    e.id, 
    e.name, 
    e.employee_number, 
    e.relation, 
    e.familyid, 
    ROW_NUMBER() OVER(PARTITION BY e.employeeid ORDER BY familyid) - 1 AS sequenceid 
    FROM employee_members e 
) a 
WHERE a.familyid <> a.sequenceid 

, şunları yapmalısınız

SELECT 
    a.employee_number, 
    MIN(a.sequence_id) AS first_missing 
FROM (
    SELECT 
    e.id, 
    e.name, 
    e.employee_number, 
    e.relation, 
    e.familyid, 
    ROW_NUMBER() OVER(PARTITION BY e.employeeid ORDER BY familyid) - 1 AS sequenceid 
    FROM employee_members e 
) a 
WHERE a.familyid <> a.sequenceid 
GROUP BY a.employee_number 

tüm eksik valu bulma: kolayca employee_number grup ve her bir çalışan için ilk eksik sekans kimliğini bulmak es önceki sorguyu genişletme

, biz familyid ve sequenceid değişiklikler arasında her seferinde bir eksik değerini fark algılayabilir:

-- Warning: this is totally untested :-/ 
SELECT 
    b.employee_number, 
    MIN(b.sequence_id) AS missing 
FROM (
    SELECT 
    a.*, 
    a.familyid - a.sequenceid AS displacement 
    SELECT 
     e.*, 
     ROW_NUMBER() OVER(PARTITION BY e.employeeid ORDER BY familyid) - 1 AS sequenceid 
    FROM employee_members e 
) a 
) b 
WHERE b.displacement <> 0 
GROUP BY 
    b.employee_number, 
    b.displacement 
+0

Bunun için gideceğim şey buydu ... lütfen bir satırda birden fazla eksik varsa işe yaramaz. – Ben

+0

Tamam, bu ilk eksik olanı gösterecek, çalışan tarafından yapılan tüm eksiklikleri elde etmek mümkün değil mi? Çok teşekkürler – VAAA

+1

En iyi çözüm, Gordon Linoff'un yanıtındaki gibi CTE (Ortak Tablo İfadeleri) kullanmaktır. Ayrıca bakınız: http://stackoverflow.com/a/5279088/238421 –

2

Bu, tüm "Bağımlı" ve önceki satırda sol birleştirmeyi seçin. o satır sonra orada değilse sonuçları:

SELECT 'Missing Prior', t1.* 
FROM employee_members t1 
LEFT JOIN employee_members t2 ON t1.employee_number = t2.employee_number 
        AND (t1.familyid-1) = t2.familyid 
WHERE t2.employee_number is null and t1.relation == 'Dependent' 

size eksik sayısını gösterir bir başka versiyonu:

SELECT t1.employee_number, t1.familyid-1 as Missing_Member 
FROM employee_members t1 
LEFT JOIN employee_members t2 ON t1.employee_number = t2.employee_number 
        AND (t1.familyid-1) = t2.familyid 
WHERE t2.employee_number is null and t1.relation == 'Dependent' 
3

İşte bir yaklaşımdır. Her çalışan için maksimum aile kimliğini hesaplayın. Ardından, maksimum aile kimliğine kadar olan numaraların listesine katılın. Sonuç, her çalışan ve beklenen aile kimliği için bir satır vardır.

Bu left outer join numaranızı, familyid numaralı numaradaki orijinal verilere geri döndürün. hiçbir şey maçları durumlarda, bu eksik değerler şunlardır: eksik familyid dizisindeki son sayı olduğunda bu işe yaramaz

with nums as (
     select 1 as n 
     union all 
     select n+1 
     from nums 
     where n < 20 
    ) 
select en.employee, n.n as MissingFamilyId 
from (select employee, min(familyid) as minfi, max(familyid) as maxfi 
     from t 
     group by employee 
    ) en join 
    nums n 
    on n.n <= maxfi left outer join 
    t 
    on t.employee = en.employee and 
     t.familyid = n.n 
where t.employee_number is null; 

Not söyledi. Ama veri yapınızla yapabileceğiniz en iyi şey olabilir. Ayrıca yukarıdaki sorguda en fazla 20 aile üyesi olduğu varsayılmaktadır.

0

Bu seçim, CTE yaklaşımı kullanılarak çalışan başına eksik "aile kimliği" listesini alır.

SORGULAMA:

WITH emp_grp (
     EmployeeID 
     ,MaxFamilyID 
     ) 
    AS (
     SELECT e2.EmployeeID 
      ,MAX(e2.FamilyID) MaxFamilyID 
     FROM employee_number e2 
     GROUP BY e2.EmployeeID 
     ) 
     ,emp_mem 
    AS (
     SELECT EmployeeID 
      ,0 AS FamilyID 
      ,MaxFamilyID 
     FROM emp_grp 

     UNION ALL 

     SELECT EmployeeID 
      ,FamilyID + 1 AS FamilyID 
      ,MaxFamilyID 
     FROM emp_mem 
     WHERE emp_mem.FamilyID < MaxFamilyID 
     ) 

    SELECT emp_mem.EmployeeID 
     ,emp_mem.FamilyID 
    FROM emp_mem 
    LEFT JOIN employee_number emp_num ON emp_mem.EmployeeID = emp_num.EmployeeID 
     AND emp_mem.FamilyID = emp_num.FamilyID 
    WHERE emp_num.EmployeeID IS NULL 
    ORDER BY emp_mem.EmployeeID 
     ,emp_mem.FamilyID 

OPTION (MAXRECURSION 32767) 

ÇIKIŞ:

EmployeeID FamilyID 
----------- ----------- 
1021  2 
1021  5 
1027  1 
1027  6 
+0

Merhaba, neden 3 tablo var mı: employee_number, emp_grp ve emp_mem? Sadece 1 masam var. – VAAA

+0

Bu hatayı alıyorum: Msg 530, Düzey 16, Durum 1, Satır 1 Bildirimi sonlandırıldı. Maksimum yineleme 100, bildirimin tamamlanmasından önce tükendi. – VAAA

+0

sorgunuzu gönderebilir misiniz? –

1

Başka bir çözüm: dizisinden bütün olası değerleri içeren bir tablo oluşturulması (bunun için kimlik ile oynayabilir). Daha sonra kaynak tablonun null olduğu tabloya katıl.

DECLARE @Seq TABLE (id INT IDENTITY(1, 1)) 
DECLARE @iter INT = 1 

WHILE @iter <= (
     SELECT MAX([your ID column]) 
     FROM [Offending Table] 
     ) 
BEGIN 
    INSERT @Seq DEFAULT 
    VALUES 

    SET @iter = @iter + 1 
END 

SELECT id 
FROM @seq s 
LEFT JOIN [Offending Table] ot ON s.id = ot.[your ID column] 
WHERE ot.[Offending Table]IS NULL