TSQL - INSERT ENTRY, если в группе не существует конкретной записи - PullRequest
0 голосов
/ 21 ноября 2018

Я пытаюсь вставить запись, если нет записи о том, что пользователь из группы вышел из системы.

declare @test table (grp varchar(2),logged varchar(4),time datetime)

insert into @test (grp,logged,time)
values ('A1', 'IN','20181111 09:00:00')
      ,('A1', 'OUT','20181111 10:00:00')
      ,('A2', 'IN','20181111 09:10:00')
      ,('A2', 'IN','20181111 09:20:00')
      ,('A3', 'IN','20181111 09:30:00') 
      ,('A3', 'OUT','20181111 10:30:00')

Желаемый вывод

+-----+--------+-------------------------+
| grp | logged |          time           |
+-----+--------+-------------------------+
| A1  | IN     | 2018-11-11 09:00:00.000 |
| A1  | OUT    | 2018-11-11 10:00:00.000 |
| A2  | IN     | 2018-11-11 09:10:00.000 |
| A2  | IN     | 2018-11-11 09:20:00.000 |
| A2  | OUT    | NULL                    |
| A2  | OUT    | NULL                    |
| A3  | IN     | 2018-11-11 09:30:00.000 |
| A3  | OUT    | 2018-11-11 10:30:00.000 |
| A4  | IN     | 2018-11-11 09:40:00.000 |
| A4  | OUT    | NULL                    |
+-----+--------+-------------------------+

Есть идеи?

1 Ответ

0 голосов
/ 21 ноября 2018

У меня есть 2 версии для вас

CREATE TABLE SignIn(grp varchar(10), logged varchar(3), [time] datetime)
INSERT INTO SignIn
VALUES
('A1','IN'  ,   '2018-11-11 09:00:00.000'   ),
('A1','OUT',    '2018-11-11 10:00:00.000'   ),
('A2','IN'  ,   '2018-11-11 09:10:00.000'   ),
('A2','IN' ,    '2018-11-11 09:20:00.000'   ),
('A3','IN'  ,   '2018-11-11 09:30:00.000'   ),
('A3','OUT',    '2018-11-11 10:30:00.000'   ),
('A4','IN',     '2018-11-11 09:40:00.000'   )

ЭТА версия соответствует вашим ожиданиям.Для каждой записи вы получите копию OUT

INSERT INTO SignIn (grp, logged, time)
SELECT s.grp, 'OUT', NULL
FROM SignIn s
INNER JOIN (
        SELECT grp
        FROM SignIn
        GROUP BY grp
        HAVING  MAX(CASE WHEN Logged = 'OUT' THEN 1 ELSE 0 END) = 0
        ) notSignedOut ON s.grp = notSignedOut.grp

Но если вы не хотите дублировать записи и хотите получить только одну запись для группы, вы можете использовать опцию ниже:

    INSERT INTO SignIn (grp, logged, time)
    SELECT grp, 'OUT', NULL
        --ISLoggedOut = MAX(CASE WHEN Logged = 'OUT' THEN 1 ELSE 0 END)
    FROM SignIn
    GROUP BY grp
    HAVING  MAX(CASE WHEN Logged = 'OUT' THEN 1 ELSE 0 END) = 0

основная логика скрыта под ISLoggedOut = MAX (CASE WHEN Logged = 'OUT' THEN 1 ELSE 0 END).Для каждой группы записей я добавил индикатор, если есть запись.и в случае, если нет - значение будет 0.

другой вариант заключается в использовании пункта «не существует»

   INSERT INTO SignIn (grp, logged, time)
   SELECT s.grp, 'OUT', NULL
   FROM SignIn s
   WHERE NOT EXISTS (SELECT TOP 1 1 FROM SignIn i WHERE i.grp = s.grp AND Logged = 'OUT')

лично я предпочитаю использовать HAVING, основываясь на некотором опыте, иногда он существует быстреедля больших столов.Например, для нашего примера оператора с наличием следующей статистики

Таблица «Рабочий стол».Сканирование счетчик 0, логическое чтение 0, физическое чтение 0, чтение с опережением 0, чтение логического объекта 0, чтение с физического объекта 0, чтение с опережением 0. Таблица 'SignIn'.Сканирование 2, логическое чтение 2, физическое чтение 0, чтение с опережением 0, чтение логического объекта 0, чтение с физического объекта 0, чтение с опережением 0. 0. 1018 *

и утверждение о существовании:

Таблица «Вход».Сканирование 2, логическое чтение 8, физическое чтение 0, чтение с опережением 0, чтение логического объекта 0, чтение с физического объекта 0, чтение с опережением чтения 0.

похоже, что оператор HAVING выполняет меньшечитает, чем существует

...