2013-07-06 2 views
6

я следующие данные в SQL таблице:SQL запрос найти недостающие порядковые номера

enter image description here

Мне нужно запросить данные, так что я могу получить список пропавших без вести «familyid» на одного работника.

Например, я должен получить для Работника 1021, который отсутствует в последовательности идентификаторов: 2 и 5, и для Работника 1027 должен получить недостающие цифры 1 и 6.

Любой ключ о том, как запросить это?

Цените любую помощь.

+0

мы не можем видеть полные имена столбцов – Hogan

+1

Последнее имя столбца - «familyid». – VAAA

+0

и имя третьего столбца и таблицы? – Hogan

ответ

3

Найти первый отсутствующее значение

I будет использовать ROW_NUMBERwindow function, чтобы назначить «правильный» идентификатор последовательности. Если предположить, что последовательность 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 

Тогда, я бы фильтровать результат включать только строки с идентификаторами не соответствующей последовательности:

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

Этот выбор будет получать список отсутствующих «familyid» для каждого сотрудника с использованием подхода 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) 

ВЫВОД:

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

Привет, почему у вас есть 3 таблицы: employee_number, emp_grp и emp_mem? У меня только 1 стол. – VAAA

+0

Im получение этой ошибки: Msg 530, уровень 16, состояние 1, строка 1 Заявление завершено. Максимальная рекурсия 100 была исчерпана до завершения заявки. – VAAA

+0

Вы можете оставить свой запрос? –

1

Другое решение: Создайте таблицу со всеми возможными значениями из последовательности (может играть с единицей для этого). Затем слева присоединитесь к таблице, где исходная таблица имеет значение 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.[Offending Table]IS NULL 
Смежные вопросы