SQL Server Query In и Out - PullRequest
       6

SQL Server Query In и Out

0 голосов
/ 07 ноября 2019

Это с устройства DTR, которое я сохранил в базе данных MS SQL

ID | Employee_ID | Date | InOutMode -------+-------------+---------------------+----------- 70821 | 104 | 2019-10-11 19:00:00 | 0 70850 | 104 | 2019-10-12 07:01:00 | 1

, если я собираюсь разделить IN и OUT, он будет выглядеть так:

ID | Employee_ID | IN | OUT -------+-------------+---------------------+----------- 70821 | 104 | 2019-10-11 19:00:00 | 2019-10-12 07:01:00

Что происходит, я не знаю, были ли мои запросы неправильными. время ожидания не 2019-10-12, а 2019-10-11 то же самое, что время ожидания, оно выглядит следующим образом:

ID | Employee_ID | IN | OUT -------+-------------+---------------------+----------- 70821 | 104 | 2019-10-11 19:00:00 | 2019-10-11 07:01:00

Ответы [ 2 ]

0 голосов
/ 08 ноября 2019

Попробуйте:

;
WITH Ins as (
  Select *
  FROM   HR_DTR_Device 
  WHERE  InOutMode = 0
),
Outs as (
  Select *
  FROM   HR_DTR_Device
  WHERE  InOutMode = 1
)
SELECT Ins.ID,
       Ins.Employee_ID,
       Ins.Date as [In],
       (
         SELECT Min(Outs.Date)
         FROM   Outs
         WHERE  Ins.Employee_ID = Outs.Employee_ID
            AND Outs.Date > Ins.Date
       ) as [Out]
FROM   Ins
WHERE  Ins.Employee_ID = '104'

Что это делает:

  1. Разделяет Ins и Outs, как если бы они были отдельными источниками данных. Использование Общих табличных выражений позволяет вам заранее задавать подзапросы и давать им имена.
  2. Для каждой записи в Ins ищет наименьшую дату из Outs это все еще больше, чем In дата. (Это предполагает, что ваши записи завершены, и что у вас никогда не будет двух Ins подряд, потому что кто-то забыл отключить время.)
  3. Не делает никаких предположений о том, когда Outпроисходит дата, просто она позже In даты (по определению). Таким образом, вам не нужно беспокоиться о том, ушел ли сотрудник позже в тот же день или в начале следующего дня (если у вас есть сотрудники, работающие в разные смены).
  4. Также будут отображаться любые записи, в которых сотрудник работално еще не вышло.

Я думаю, что ваша большая ошибка была здесь:

 (SELECT MAX(Date) FROM HR_DTR_Device XX 
 WHERE InOutMode = 1
   AND XX.Employee_ID = AA.Employee_ID
   AND CAST(XX.Date AS DATE) = CAST(AA.Date AS DATE)) AS 'Out'

Вы возвращаете самую большую дату для этого сотрудника, которая находится в ту же календарную дату (и является Out). Но если сотрудник работает до следующего утра, дата изменится!

Вы можете исправить это, изменив свой тест на следующее:

CAST(DATEADD(d, -1, XX.Date) AS DATE) = CAST(AA.Date AS DATE)

... но тогда это произойдетРаботайте ТОЛЬКО для сотрудников, которые работали всю ночь, в то время как мое решение просто находит следующий раз, когда сотрудник отключился после того, как он включился, независимо от того, будет ли это тот же день, следующий день или следующая неделя!

Если вам нравится это решение, отметьте его как принятое. Спасибо.

0 голосов
/ 07 ноября 2019

Попробуйте,

DECLARE @Temp_Table Table
(
    Empoyee_id int,
    [Date] datetime,
    [InOutMode] bit
)

INSERT INTO @Temp_Table
(
    Empoyee_id,[Date],[InOutMode]

)
SELECT 104,'20191011 09:30',1 
UNION ALL
SELECT 104,'20191011 19:30',0 
UNION ALL
SELECT 104,'20191012 09:30',1 
UNION ALL
SELECT 104,'20191012 12:30',0 
UNION ALL
SELECT 104,'20191012 19:00',0 
UNION ALL
SELECT 104,'20191013 09:30',1 
UNION ALL
SELECT 104,'20191013 07:30',0
UNION ALL
SELECT 104,'20191014 09:30',1 

SELECT Empoyee_id,[Date],[In],IIF([In]>[Out],null,[Out]) as [Out]
FROM
(
    SELECT Empoyee_id,CAST([Date] AS DATE) AS [Date],
    MIN(IIF(InOutMode=1,[Date],NULL)) AS [In] ,
    MAX(IIF(InOutMode=0,[Date],NULL)) AS [Out]
    FROM @Temp_Table
    GROUP BY Empoyee_id,CAST([Date] AS DATE)
)A
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...