2013-07-06 53 views
6

我在一個SQL表以下數據:SQL查詢找到失蹤的連續編號

enter image description here

我需要查詢的數據,所以我可以得到失蹤名單每名員工「FAMILYID」。

舉例來說,我應該得到員工1021缺少序列中的ID:2和5以及爲職工1027應該得到丟失號碼1和6

關於如何查詢任何線索?

感謝任何幫助。

+0

我們無法看到完整的列名 – Hogan

+1

最後一列名稱是「familyid」。 – VAAA

+0

和第三列和表名? – Hogan

回答

3

找到的第一個缺失值

我將使用ROW_NUMBERwindow function來分配「正確的」序列ID號碼。假設序列ID重新開始,每次員工ID的變化:

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 

然後,我會篩選結果設置爲只包括與錯配序列ID的行:

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 

話又說回來,你應該容易被employee_number組,並找到爲每個員工第一丟失的序列ID:

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 

找到所有失蹤VALU ES

擴展前面的查詢,我們每次都能檢測到缺少值之差familyidsequenceid變化之間:

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

這就是我要去的地方...請注意,如果連續失蹤多於一個,它不起作用。 – Ben

+0

好吧,這會顯示第一個失蹤,是不可能得到員工的所有錯誤?非常感謝 – VAAA

+1

最好的解決方案是使用CTE(Common Table Expressions),就像在Gordon Linoff的回答中一樣。另請參閱:http://stackoverflow.com/a/5279088/238421 –

2

這將起作用,您選擇所有「依賴者」,並在前一行中加入左連接。如果該行不存在,那麼你顯示結果:

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' 

另一個版本,顯示你丟失的數量:

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

這是一種方法。計算每位員工的最大家庭標識。然後將其加入到最大家庭編號的數字列表中。結果對於每個員工和預期的家庭標識都有一行。

做一個left outer join從這回到原始數據,在familyid和數字。凡沒有匹配項,這些都是缺失值:

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; 

注意,當缺少familyid是序列中的最後一個數字,這將不起作用。但它可能是你可以用你的數據結構做的最好的。

另外,上述查詢假定最多有20個家庭成員。

0

此選擇將使用CTE方法檢索每位員工缺失的「familyid」列表。

QUERY:

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) 

OUTPUT:

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

嗨,爲什麼你有3個表:employee_number,emp_grp和emp_mem?我只有一張桌子。 – VAAA

+0

我得到這個錯誤:消息530,級別16,狀態1,行1 聲明終止。報表完成前,最大遞歸100已用盡。 – VAAA

+0

你能發表你的查詢嗎? –

1

另一種解決方案: 建立了從序列的所有可能值的表(可以用這個身份出戰)。然後在源表爲空的表上留下加入。

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