Check if there's an existing record on the day before

让人想犯罪 __ 提交于 2020-01-25 06:48:25

问题


I'm trying to check if there's an existing record on the day before the selected schedule date. How do we do this? I tried using LAG(), but I'm having problem when it comes to sorting out the data because of the NULL.

DATEDIFF() won't solve my problem as well because I need to check if there's an existing data on that date, and not -1 the date.

What I want to query if example. Day before 2020-01-02 has recordin and recordout, it should reflect NULL if necessary. Is there a way to do this?

This will be the result.

scheduledate   schedulein         scheduleout        recordin           recordout          prevrecordin      prevrecordout
2020-01-02     08:00:00.0000000   17:00:00.0000000   07:41:12.0000000   17:16:54.0000000   NULL               NULL

prevrecordin and prevrecordout will be both NULL since 2020-01-01 is NULL.

This is first table.

badgenumber checktype   recordin                    checkdate
10          I           2019-12-20 07:35:58.000     2019-12-20
10          I           2019-12-21 05:18:14.000     2019-12-21
10          I           2019-12-23 07:35:33.000     2019-12-23
10          I           2019-12-26 07:48:20.000     2019-12-26
10          I           2019-12-27 07:41:03.000     2019-12-27
10          I           2019-12-28 07:35:42.000     2019-12-28
10          I           2020-01-02 07:41:12.000     2020-01-02
10          I           2020-01-03 07:50:12.000     2020-01-03
10          I           2020-01-04 07:41:12.000     2020-01-04

This query is being processed by this.

.....
OUTER APPLY (
                    SELECT TOP(1) t1.recordin, t1.badgenumber
                    FROM (SELECT MAX(userinfo.badgenumber) AS badgenumber, MAX(RTRIM(checkinout.checktype)) AS 'checktype', 
                    MIN(checkinout.checktime) as 'recordin', MIN(CONVERT(date,checkinout.checktime)) as checkdate, 
                    MAX(RTRIM(employeemasterfile.employeeidno)) AS 'employeeidno' 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 DATEADD(DAY, -1,'2019-12-21') AND DATEADD(DAY, 1,'2020-01-05') and badgenumber = '10'
                    AND CHECKINOUT.CHECKTYPE = 'I' COLLATE SQL_Latin1_General_CP1_CS_AS GROUP BY userinfo.badgenumber, LEFT(checkinout.checktime,14)) AS t1
                     WHERE 
                        t1.recordin BETWEEN DATEADD(HOUR,-(t0.noofhoursduty),t0.mergetimeinorig) AND DATEADD(HOUR, (t0.noofhoursduty),t0.mergetimeinorig)
                        AND t1.badgenumber = t0.fingerscanno
                        AND t0.schedulename !='REST'
                     ORDER BY abs(datediff(minute, t0.mergetimeinorig, t1.recordin )) DESC

                    ) t1

This is the second table.

badgenumber checktype   recordout               checkdate
10          O           2019-12-20 20:41:46.000 2019-12-20
10          O           2019-12-21 14:12:34.000 2019-12-21
10          O           2019-12-23 17:03:44.000 2019-12-23
10          O           2019-12-26 17:05:16.000 2019-12-26
10          O           2019-12-27 17:02:32.000 2019-12-27
10          O           2019-12-28 17:07:38.000 2019-12-28
10          O           2020-01-02 17:16:54.000 2020-01-02
10          O           2020-01-03 17:05:11.000 2020-01-03
10          O           2020-01-04 17:04:42.000 2020-01-04

This is being processed by this query.

OUTER APPLY (
                    SELECT TOP(1) t2.recordout, t2.badgenumber
                    FROM (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' 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 DATEADD(DAY, -1,'2019-12-21') AND DATEADD(DAY, 1,'2020-01-05') and badgenumber = '10'
                    AND CHECKINOUT.CHECKTYPE = 'O' COLLATE SQL_Latin1_General_CP1_CS_AS GROUP BY userinfo.badgenumber, LEFT(checkinout.checktime,14)) AS t2
                     WHERE 
                        t2.recordout BETWEEN DATEADD(HOUR,-(t0.noofhoursduty),t0.mergetimeoutorig) AND DATEADD(HOUR, (t0.noofhoursduty),t0.mergetimeoutorig)
                        AND t2.badgenumber = t0.fingerscanno
                        AND t0.schedulename !='REST'
                     ORDER BY abs(datediff(minute, t0.mergetimeoutorig, t2.recordout )) DESC
                    ) t2

This is the query result.

for t1.recordin, and t2.recordout, scheduledate comes from t0.scheduledate with the corresponding date on the table respectively.

scheduledate   schedulein         scheduleout        recordin           recordout
2019-12-21     06:00:00.0000000   14:00:00.0000000   05:18:14.0000000   14:12:34.0000000
2019-12-23     08:00:00.0000000   17:00:00.0000000   07:35:33.0000000   17:03:44.0000000
2019-12-24     08:00:00.0000000   17:00:00.0000000   NULL               NULL
2019-12-25     08:00:00.0000000   17:00:00.0000000   NULL               NULL
2019-12-26     08:00:00.0000000   17:00:00.0000000   07:48:20.0000000   17:05:16.0000000
2019-12-27     08:00:00.0000000   17:00:00.0000000   07:41:03.0000000   17:02:32.0000000
2019-12-28     08:00:00.0000000   17:00:00.0000000   07:35:42.0000000   17:07:38.0000000
2019-12-30     08:00:00.0000000   17:00:00.0000000   NULL               NULL
2019-12-31     08:00:00.0000000   17:00:00.0000000   NULL               NULL
2020-01-01     08:00:00.0000000   17:00:00.0000000   NULL               NULL
2020-01-02     08:00:00.0000000   17:00:00.0000000   07:41:12.0000000   17:16:54.0000000
2020-01-03     08:00:00.0000000   17:00:00.0000000   07:50:12.0000000   17:05:11.0000000
2020-01-04     08:00:00.0000000   17:00:00.0000000   07:41:12.0000000   17:04:42.0000000

I tried doing CASE WHEN (LAG()) as well, unfortunately I am unable to do it because of the NULL value as well.

What I need to achieve is a new column that will display somewhat like this.

Similar expected result.

scheduledate    schedulein  scheduleout recordin    recordout   prevrecordin    prevrecordout
21/12/2019      06:00:00    14:00:00    05:18:14    14:12:34    NULL            NULL
23/12/2019      08:00:00    17:00:00    07:35:33    17:03:44    05:18:14        14:12:34
24/12/2019      08:00:00    17:00:00    NULL        NULL        07:35:33        17:03:44
25/12/2019      08:00:00    17:00:00    NULL        NULL        NULL            NULL
26/12/2019      08:00:00    17:00:00    07:48:20    17:05:16    NULL            NULL
27/12/2019      08:00:00    17:00:00    07:41:03    17:02:32    07:48:20        17:05:16
28/12/2019      08:00:00    17:00:00    07:35:42    17:07:38    07:41:03        17:02:32
30/12/2019      08:00:00    17:00:00    NULL        NULL        07:35:42        17:07:38
31/12/2019      08:00:00    17:00:00    NULL        NULL        NULL            NULL
01/01/2020      08:00:00    17:00:00    NULL        NULL        NULL            NULL
02/01/2020      08:00:00    17:00:00    07:41:12    17:16:54    NULL            NULL
03/01/2020      08:00:00    17:00:00    07:50:12    17:05:11    07:41:12        17:16:54
04/01/2020      08:00:00    17:00:00    07:41:12    17:04:42    07:50:12        17:05:11

Your help would be greatly appreciated. Thank you.


回答1:


Based on your sample data, I am assuming the following:

  • At most record per badge per day.
  • recordin and recordout on the same day.
  • checktype is irrelevant
  • You know how to generate the data in the original table.

If so, you can use lag():

select t.*,
       (case when datediff(day,
                           lag(recordin) over (partition by badgenumber order by recordin),
                           recordin
                          ) <> 1
             then null
             else lag(recordin) over (partition by badgenumber order by recordin)
       end),
       (case when datediff(day,
                           lag(recordin) over (partition by badgenumber order by recordin),
                           recordin
                          ) <> 1
             then null
             else lag(recordout) over (partition by badgenumber order by recordin)
       end),
from t;

If the above are not true, I would suggest that you ask a new question. Try to simplify the problem. Your rather complex query has nothing to do with the question you are asking, so it doesn't help the question.



来源:https://stackoverflow.com/questions/59747074/check-if-theres-an-existing-record-on-the-day-before

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!