У меня проблема с тем, как это сделать, используя LEFTJOIN. Есть ли способ для LEFT JOIN
и ON
специально выбрать только ближайшее значение в запросе, где оно будет LEFT JOIN
?
Например, у меня есть значения из запроса как эта таблица ниже, которая отсортирована на основе контрольной даты, и я отсортировал значение на основе 2019-12-25 . Я только хочу выбрать значение, наиболее близкое к 2019-12-25 14: 50: 00.000 , так что технически единственное значение, которое следует использовать, это 2019-12-25 14: 51: 57.000 поскольку он ближайший, как мы можем это сделать, используя LEFT JOIN
?
+-------------+-----------+-------------------------+------------+
| badgenumber | checktype | recordout | checkdate |
+-------------+-----------+-------------------------+------------+
| 1233 | O | 2019-12-25 14:00:02.000 | 2019-12-25 |
+-------------+-----------+-------------------------+------------+
| 1233 | O | 2019-12-25 14:39:57.000 | 2019-12-25 |
+-------------+-----------+-------------------------+------------+
| 1233 | O | 2019-12-25 14:51:57.000 | 2019-12-25 |
+-------------+-----------+-------------------------+------------+
| 1233 | O | 2019-12-25 22:41:57.000 | 2019-12-25 |
+-------------+-----------+-------------------------+------------+
| 1233 | O | 2019-12-25 22:52:57.000 | 2019-12-25 |
+-------------+-----------+-------------------------+------------+
Это запрос, над которым я работаю, employeeidno, fullname, departmentname
скрыты.
Используются следующие значения:
- t0.noofhoursduty = 8
- t0.mergetimeoutorig = 2019-12-25 14: 50: 00.000
Это запрос, включающий LEFT JOIN
.
LEFT JOIN
(SELECT
MAX(userinfo.badgenumber) AS badgenumber,
MAX(RTRIM(checkinout.checktype)) AS 'checktype',
MAX(checkinout.checktime) as 'recordout',
MAX(CONVERT(date,checkinout.checktime)) as checkdate,
MAX(RTRIM(employeemasterfile.employeeidno)) AS 'employeeidno',
MAX(RTRIM(employeemasterfile.lastname))+', '+
MAX(RTRIM(employeemasterfile.firstname))+' '+ MAX(LEFT(employeemasterfile.middlename,1))+'.' AS 'fullname',
MAX(RTRIM(departmentmasterfile.departmentname)) AS 'departmentname'
FROM ((checkinout INNER JOIN userinfo
ON checkinout.userid = userinfo.userid)
INNER JOIN employeemasterfile
ON userinfo.badgenumber = employeemasterfile.fingerscanno)
INNER JOIN departmentmasterfile
ON LEFT(employeemasterfile.employeeidno, 4) = LEFT(departmentmasterfile.departmentcode, 4)
WHERE
CONVERT(date,checkinout.checktime) BETWEEN '2019-12-21' AND DATEADD(DAY, 1,'2020-01-05')
AND CHECKINOUT.CHECKTYPE = 'O' COLLATE SQL_Latin1_General_CP1_CS_AS
GROUP BY
userinfo.badgenumber, LEFT(checkinout.checktime,14)) AS t2
ON
t2.recordout BETWEEN DATEADD(HOUR,-(t0.noofhoursduty/2),t0.mergetimeoutorig) AND DATEADD(HOUR, 1,t0.mergetimeoutorig)
AND t2.badgenumber = t0.fingerscanno
AND t0.schedulename !='REST'
Это будет вывод запроса выше. Тот же результат с датой - это нормально, потому что есть случаи, когда человек входит в систему 4 раза в день в разные временные метки. Или у человека есть 2 или более графика в течение дня.
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| badgenumber | checktype | recordout | checkdate | employeeidno | fullname | departmentname |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-21 23:43:36.000 | 2019-12-21 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-22 22:36:50.000 | 2019-12-22 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-23 18:03:16.000 | 2019-12-23 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-24 22:06:58.000 | 2019-12-24 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-25 14:00:02.000 | 2019-12-25 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-25 14:39:57.000 | 2019-12-25 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-25 14:51:57.000 | 2019-12-25 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-25 22:41:57.000 | 2019-12-25 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-25 22:52:57.000 | 2019-12-25 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-26 14:00:02.000 | 2019-12-26 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-28 22:00:01.000 | 2019-12-28 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-28 23:31:11.000 | 2019-12-28 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-29 15:08:10.000 | 2019-12-29 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2019-12-30 16:03:20.000 | 2019-12-30 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2020-01-02 06:52:18.000 | 2020-01-02 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2020-01-03 08:00:57.000 | 2020-01-03 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
| 1233 | O | 2020-01-04 06:40:11.000 | 2020-01-04 | ------------ | -------- | -------------- |
+-------------+-----------+-------------------------+------------+--------------+----------+----------------+
Кажется, что то, что у меня сейчас есть, работает, но когда есть большие различия во временной отметке, данные дублируются, например, если человек отметки времени 'O' (контрольный тип) Примерно в 12:00 - 9:00 и повторное нажатие в 10:00 - 7:00 , запись покажет 2 данных в одну и ту же дату, и это нормально, мой главный проблема в том, как выбрать только ближайшее значение по сравнению с ним в LEFT JOIN
?
Подводя итог, можно ли будет LEFT JOIN
выбрать только самое близкое значение на основе записи, если я будет использоваться 2019-12-25 14: 50: 00.000 в качестве основы для LEFT JOIN, тогда для LEFT JOIN следует выбрать только 2019-12-25 14: 51: 57.000, Я попытался использовать BETWEEN
и DATEADD(-+HOUR)
, но он все еще выбирает все данные в одной записи. Есть ли способ сделать это? или это правдоподобно, используя только LEFT JOIN
?
Есть ли способ изменить эту строку кодов для достижения моей цели?
ON
t2.recordout BETWEEN DATEADD(HOUR,-(t0.noofhoursduty/2),t0.mergetimeoutorig) AND DATEADD(HOUR, 1,t0.mergetimeoutorig)
AND t2.badgenumber = t0.fingerscanno
AND t0.schedulename !='REST'
Надеясь на положительный ответ, это ошибка я долгое время о том, как сделать это с помощью LEFT JOIN.