6

SQL テーブルに次のデータがあります。

ここに画像の説明を入力

欠落している「 familyid 」のリストを従業員ごとに取得できるように、データを照会する必要があります。

たとえば、シーケンスに欠落している従業員 1021 については ID 2 と 5 を取得し、従業員 1027 については欠落している番号 1 と 6 を取得する必要があります。

それを照会する方法の手がかりはありますか?

どんな助けにも感謝します。

4

5 に答える 5

3

ここに 1 つのアプローチがあります。各従業員の家族 ID の最大値を計算します。次に、これを最大家族 ID までの番号のリストに結合します。結果には、各従業員と予想される家族 ID ごとに 1 つの行があります。

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 人の家族がいると想定しています。

于 2013-07-06T15:53:00.987 に答える
3

最初の欠損値を見つける

ROW_NUMBER ウィンドウ関数を使用して、「正しい」シーケンス 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

すべての欠損値を見つける

familyid前のクエリを拡張すると、との差がsequenceid変化するたびに欠損値を検出できます。

-- 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
于 2013-07-06T15:51:36.697 に答える
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'
于 2013-07-06T15:36:36.863 に答える
2

別の解決策: シーケンスから考えられるすべての値を含むテーブルを作成します (このための ID で遊ぶことができます)。次に、ソース テーブルが null であるテーブルで左結合します。

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.[your ID column] IS NULL
于 2015-06-02T01:15:53.810 に答える