2013-07-06 10 views
6

が欠け見つける:SQLクエリは、私はSQLの表で、次のデータを持っている連続した番号に

enter image description here

私は従業員一人当たりの行方不明「familyid」のリストを得ることができるので、データを照会する必要があります。

例えば、私はIDが順番に欠けている従業員1021のために取得する必要があります:2と5と従業員1027のために取得する必要欠番1と6

ことを照会する方法上の任意の手がかり?

ありがとうございました。

+0

完全な列名は表示されません – Hogan

+1

最後の列名は "familyid"です。 – VAAA

+0

と第3列とテーブル名? – 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 

は、あなたがすべき

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を見つける:簡単employee_numberでグループとは、各従業員のための最初の欠落しているシーケンスIDを見つけます前のクエリを拡張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

最高の解決策は、Gordon LinoffのanswserのようにCTE(Common Table Expressions)を使用することです。以下も参照してください: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

は一つの方法です。各従業員の最大家族IDを計算します。次に、これを最大ファミリーIDまでの数字のリストに加えます。結果には、各従業員と期待される家族IDに対して1つの行があります。

left outer joinを元のデータのfamilyidと番号に戻してください。行方不明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; 

注:何も一致しない場合には、それらは欠損値です。しかし、あなたがあなたのデータ構造でできることは最高かもしれません。

また、上記のクエリでは、最大20の家族がいると仮定しています。

0

この選択は、CTEアプローチを使用して、従業員一人につき欠落した「ファミリ」のリストを取得します。

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

employee_number、emp_grp、emp_memの3つのテーブルがありますか?私はただ1つのテーブルを持っています。 – 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 
関連する問題