Создание строк входа и выхода из одной строки

У меня вход и выход такой.

DECLARE @t TABLE
           (
               id INT IDENTITY(1, 1), 
               empid VARCHAR(10), 
               logindate DATE, 
               logintime TIME, 
               logoutdate DATE, 
               logouttime TIME
           )

INSERT @t (empid, logindate, logintime, logoutdate, logouttime) VALUES('251803', CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T08:00:00.000' AS TIME), CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T11:00:00.000' AS TIME))
INSERT @t (empid, logindate, logintime, logoutdate, logouttime) VALUES ('251803', CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T12:00:00.000' AS TIME), CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T16:59:00.003' AS TIME))
INSERT @t (empid, logindate, logintime, logoutdate, logouttime) VALUES ('251809', CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T08:00:00.000' AS TIME), CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T10:14:00.003' AS TIME))
INSERT @t (empid, logindate, logintime, logoutdate, logouttime) VALUES ('251809', CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T11:13:00.000' AS TIME), CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T17:20:00.003' AS TIME))
INSERT @t (empid, logindate, logintime, logoutdate, logouttime) VALUES ('251800', CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T08:00:00.000' AS TIME), CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T13:08:00.003' AS TIME))
INSERT @t (empid, logindate, logintime, logoutdate, logouttime) VALUES('251800', CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T14:08:00.003' AS TIME), CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T17:00:00.003' AS TIME))
INSERT @t (empid, logindate, logintime, logoutdate, logouttime) VALUES ('251800', CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T18:00:00.003' AS TIME), CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T18:00:00.003' AS TIME))
INSERT @t (empid, logindate, logintime, logoutdate, logouttime) VALUES('251800', CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T20:08:00.003' AS TIME), CAST(N'2024-06-28T00:00:00.000' AS DATETIME), CAST(N'1899-12-30T21:00:00.003' AS TIME))

Мне нужно вывести это так:

Я написал этот SQL-скрипт

DECLARE @clock TABLE 
               (
                   i INT IDENTITY,  
                   empid VARCHAR(10), 
                   datetimelog DATETIME, 
                   log_status VARCHAR(10), 
                   punch VARCHAR(10)
               )

DECLARE @i INT = 1, @pnum INT, @curempid VARCHAR(10)

DECLARE @empid VARCHAR(10), 
        @logindate DATE, @logintime TIME, 
        @logoutdate DATE, @logouttime TIME

WHILE (@i <= (SELECT MAX(id)FROM @t))
BEGIN
    SELECT 
        @empid = empid, 
        @logindate = logindate, @logintime = logintime, 
        @logoutdate = logoutdate, @logouttime = logouttime
    FROM 
        @t 
    WHERE 
        id = @i 
    ORDER BY 
        empid, logindate

        
    IF (@curempid IS NULL)
    BEGIN
        SET @curempid = @empid
        SET @pnum = 1
    END
    ELSE
    BEGIN
        IF (@curempid = @empid)
        BEGIN
            SET @pnum = @pnum + 1
        END
        ELSE
        BEGIN
            SET @curempid = @empid
            SET @pnum = 1
        END
    END

    INSERT INTO @clock (empid, datetimelog, log_status, punch)
    VALUES (@empid, CAST(@logindate AS DATETIME) + CAST(CAST(@logintime AS TIME) AS DATETIME), 'IN', @pnum)
        
    SET @pnum = @pnum + 1
        
    INSERT INTO @clock (empid, datetimelog, log_status, punch)
    VALUES (@empid, CAST(@logoutdate AS DATETIME) + CAST(CAST(@logouttime AS TIME) AS DATETIME), 'OUT', @pnum)

    SET @i = @i + 1;
END;

Есть ли лучший способ сделать это? Я думаю о повороте, но я не знаю способа поворота. заранее спасибо

Какие СУБД вы используете? (Приведенный выше код зависит от продукта.)

jarlh 01.07.2024 21:34

mssql брат..

Dante Salvador 01.07.2024 21:56
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
2
75
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете просто объединить два набора результатов, созданных из одной таблицы, а затем добавить ROW_NUMBER(), используя оконную функцию, чтобы добиться этого.

Поскольку вы не упомянули свою СУБД, я не объединил вашу дату и отметку времени, поскольку это будет зависеть от платформы. Кроме того, если вы используете более старую версию MySQL, которая не поддерживает оконные функции, эту логику необходимо будет изменить.

SELECT empid,
    datelog,
    timelog,
    log_status,
    ROW_NUMBER() OVER (PARTITION BY empid ORDER BY datelog, timelod) as punch
FROM 
  (
    SELECT empid, 
        logindate as datelog, 
        logintime as timelog, 
        CAST('IN' as VARCHAR(10)) as log_status,
    FROM @t 
    UNION ALL
    SELECT empid, 
        logoutdate,
        logouttime, 
        'OUT',
    FROM @t 
  )dt 
ORDER BY empid, datelog, timelog

Поскольку вы используете SQL Server, вы можете использовать CROSS APPLY ... VALUES, чтобы разделить каждую исходную строку на две выходные строки. БД Скрипка

WITH T AS
(
SELECT 
        2 * ROW_NUMBER() OVER (PARTITION BY empid ORDER BY id)-1 AS punch_base,
        2 * ROW_NUMBER() OVER (ORDER BY id)-1 AS i_base,
        *
FROM @t
)
SELECT i = i_base + base_offset,
       empid,
       datelog, 
       timelog,
       log_status,
       punch = punch_base + base_offset
FROM T
CROSS APPLY (VALUES
    (logindate, logintime, 'IN', 0),
    (logoutdate, logouttime, 'OUT', 1)
)V(datelog, timelog, log_status, base_offset)

Другие вопросы по теме

Похожие вопросы

Почему метод Timestamp.of() в java.sql неправильно преобразуется из LocalDateTime в java.time?
Как использовать индекс, если искомый столбец не индексирован, но имеет тот же порядок, что и индексированный первичный ключ
Как получить информацию о самоанализе движка SQLite через Rust SQLx?
Отобразить среднее количество дней между последней и предпоследней транзакцией клиента
Как запросить фрейм данных Snowpark с помощью SQL из Snowflake?
Как устранить ошибку «Ошибка компиляции SQL: объект SNOWPARK_TEMP_STAGE_FLGVIWVUC уже существует». проблема в снежинке?
Как объединить две или более строк и СУММИРОВАТЬ столбец в ОБНОВЛЕНИИ без первичного ключа?
Левая часть выражения LIKE должна иметь значение varchar (фактически: varbinary). Какая альтернатива преобразованию varbinary в varchar?
Чтобы получить предыдущую запись, которая меньше заданной даты и времени
Выберите строки с тем же кодом товара, но с другим значением в другом столбце