source

레코드를 단일 레코드로 선택하여 시간 차이를 확인하는 방법

lovecheck 2022. 12. 18. 08:39
반응형

레코드를 단일 레코드로 선택하여 시간 차이를 확인하는 방법

직원의 움직임을 추적하기 위해 사용하는 서드파티 크로킹 어플리케이션이 있습니다.MariaDB로 동작하지만 상당히 지저분합니다(imo).프런트엔드는 윈도우 기반이며 모든 처리는 거기서 이루어집니다.문제는 실시간 보고를 위해 데이터를 추출하고 싶다는 것입니다.

클로킹 액티비티는 모두 1개의 테이블에 저장됩니다.아래 샘플을 참조하십시오.

INDX    _DATE_      _TIME_      SURNAME WIEGANDID       ZKINOUT
51      2018/09/03  5:52:04     Thakadu 000000000000AE  0
198     2018/09/03  14:04:29    Thakadu 000000000000AE  1
309     2018/09/03  21:54:06    Mabeo   000000000000BA  0
370     2018/09/04  5:47:20     Thakadu 000000000000AE  0
401     2018/09/04  6:00:09     Mabeo   000000000000BA  1
557     2018/09/04  14:04:57    Thakadu 000000000000AE  1
691     2018/09/04  21:53:33    Mabeo   000000000000BA  0
748     2018/09/05  5:47:20     Thakadu 000000000000AE  0
780     2018/09/05  6:00:34     Mabeo   000000000000BA  1
946     2018/09/05  14:05:32    Thakadu 000000000000AE  1
1089    2018/09/05  21:49:48    Mabeo   000000000000BA  0
1144    2018/09/06  5:50:41     Thakadu 000000000000AE  0
1174    2018/09/06  6:00:16     Mabeo   000000000000BA  1
1328    2018/09/06  14:09:28    Thakadu 000000000000AE  1
1482    2018/09/06  21:50:32    Mabeo   000000000000BA  0
1568    2018/09/07  5:58:48     Thakadu 000000000000AE  0
1555    2018/09/07  6:01:01     Mabeo   000000000000BA  1
1812    2018/09/07  14:05:47    Thakadu 000000000000AE  1
1845    2018/09/07  21:51:31    Mabeo   000000000000BA  0

문제는 Mabeo가 22:00:00부터 다음날 06:00:00까지 일하는 곳에서 발생합니다.또한 직원이 어떤 이유로 퇴실하지 않을 수도 있습니다.그러면 시스템은 시간을 기록하지 않고 자동으로 로그아웃합니다.

제가 보고 싶은 결과는 다음과 같습니다.

DATE_IN     TIME_IN    DATE_OUT    TIME_OUT    SURNAME    WIEGANDID
2018/09/03  05:52:04   2018/09/03  14:04:29    Thakadu    000000000000AE    
2018/09/03  21:54:06   2018/09/04  06:00:09    Mabeo      000000000000BA
2018/09/04  05:47:20   2018/09/04  14:04:57    Thakadu    000000000000AE
2018/09/04  21:53:33   2018/09/05  06:00:16    Mabeo      000000000000BA

이렇게 하면 각 이메일이 일정 기간 동안 기록된 실제 시간을 계산할 수 있습니다.

GROUP BY와 CASE를 사용하여 어느 정도 성공을 거둘 수 있었습니다만, 문제는 야간 근무에 있습니다.

어떤 도움이라도 주시면 감사하겠습니다.

---------------------------------------------------------------------

네, 기여해 주신 모든 분들께 감사드립니다.거의 다 맞혔는데 아직 100%는 못 맞췄어요.@rf1234의 제안대로 아래 코드를 사용했습니다.답변 감사합니다.

SELECT COALESCE (a.DATE_IN, b.DATE_IN)                  AS DATE_IN,
       SUBSTR(COALESCE (a.TIME_IN, b.TIME_IN), 1, 8)    AS TIME_IN,
       CASE WHEN ( b.DATE_TIME_OUT > a.DATE_TIME_IN ) THEN COALESCE (a.DATE_OUT, 
            b.DATE_OUT) ELSE '' END                     AS DATE_OUT,
       CASE WHEN ( b.DATE_TIME_OUT > a.DATE_TIME_IN ) THEN 
            SUBSTR(COALESCE (a.TIME_OUT, b.TIME_OUT), 1, 8) ELSE '' END
                                                        AS TIME_OUT,
       COALESCE (a.SURNAME, b.SURNAME)                  AS SURNAME,
       COALESCE (a.WIEGANDID, b.WIEGANDID)              AS WIEGANDID,
       CASE WHEN ( b.DATE_TIME_OUT > a.DATE_TIME_IN ) THEN
            TIMESTAMPDIFF(SECOND, a.DATE_TIME_IN, b.DATE_TIME_OUT) / 3600 ELSE '' END
                                                        AS HOURS_WORKED
FROM (
    SELECT  _DATE_  AS  DATE_IN,
            _TIME_  AS  TIME_IN,
            NULL    AS  DATE_OUT,
            NULL    AS  TIME_OUT,
            SURNAME,
            WIEGANDID,
            CONCAT( _DATE_, ' ', _TIME_ ) AS DATE_TIME_IN
          FROM _2018_09
         WHERE ZKINOUT = 0 AND SURNAME = 'MABEO'
         GROUP BY WIEGANDID, _DATE_ )   AS   a,
    (

    SELECT  NULL    AS  DATE_IN,
        NULL    AS  TIME_IN,
        _DATE_  AS  DATE_OUT,
        _TIME_  AS  TIME_OUT,
        SURNAME,
        WIEGANDID,
        CONCAT( _DATE_, ' ', _TIME_ ) AS DATE_TIME_OUT
      FROM _2018_09
     WHERE ZKINOUT = 1 AND SURNAME = 'MABEO'
     GROUP BY WIEGANDID, _DATE_)   AS   b
WHERE a.WIEGANDID = b.WIEGANDID
ORDER BY 1, 2, 3, 4

지금은 한 명의 직원만 뽑도록 코드를 수정했습니다.내가 얻는 결과는 거의 내가 원하는 것이다. 단, 테이블 a의 각 레코드와 테이블 b의 각 레코드가 결합되는 것 같다.다음은 결과의 샘플 이미지입니다.

결과 집합의 샘플

마스터 ArsuKa가 말했듯이 데이터베이스를 재설계하면 물론 훨씬 더 쉽게 만들 수 있습니다.하지만 당신이 가진 것만으로 우리가 당신의 결과를 얻을 수 있을지 지켜봅시다.또, 임시 테이블내의 2개의 타임스탬프를 분산하는 것으로, 시프트가 이미 종료했을 경우에 대비해, 작업 시간(플로트 번호)을 계산합니다.임시 DATE_ 사용TIME 컬럼은 야간 근무 중인 직원의 문제를 해결합니다.근무조가 다른 날에 끝나든 간에 그 계산은 옳다.

SELECT COALESCE (a.DATE_IN, b.DATE_IN)                  AS DATE_IN,
       SUBSTR(COALESCE (a.TIME_IN, b.TIME_IN), 1, 8)    AS TIME_IN,
       CASE WHEN ( b.DATE_TIME_OUT > a.DATE_TIME_IN ) THEN COALESCE (a.DATE_OUT, 
            b.DATE_OUT) ELSE '' END                     AS DATE_OUT,
       CASE WHEN ( b.DATE_TIME_OUT > a.DATE_TIME_IN ) THEN 
            SUBSTR(COALESCE (a.TIME_OUT, b.TIME_OUT), 1, 8) ELSE '' END
                                                        AS TIME_OUT,
       COALESCE (a.SURNAME, b.SURNAME)                  AS SURNAME,
       COALESCE (a.WIEGANDID, b.WIEGANDID)              AS WIEGANDID,
       CASE WHEN ( b.DATE_TIME_OUT > a.DATE_TIME_IN ) THEN
            TIMESTAMPDIFF(SECOND, a.DATE_TIME_IN, b.DATE_TIME_OUT) / 3600 ELSE '' END
                                                        AS HOURS_WORKED
FROM (
    SELECT  _DATE_  AS  DATE_IN,
            _TIME_  AS  TIME_IN, 
            NULL    AS  DATE_OUT,
            NULL    AS  TIME_OUT,
            SURNAME,
            WIEGANDID,
            CONCAT( _DATE_, ' ', _TIME_ ) AS DATE_TIME_IN
       FROM test 
      WHERE ZKINOUT = 0 )   AS   a,
    (
    SELECT  NULL    AS  DATE_IN,
            NULL    AS  TIME_IN, 
            _DATE_  AS  DATE_OUT,
            _TIME_  AS  TIME_OUT,
            SURNAME,
            WIEGANDID,
            CONCAT( _DATE_, ' ', _TIME_ ) AS DATE_TIME_OUT
       FROM test
      WHERE ZKINOUT = 1 )   AS   b
WHERE a.WIEGANDID = b.WIEGANDID  
HAVING HOURS_WORKED < 15 AND HOURS_WORKED <> ''
ORDER BY 1, 2, 3, 4

이것은 조금 복잡해 보이고 다음과 같은 처리를 합니다.2개의 임시 테이블 a와 b가 생성됩니다.다음은()의 SELECT 문입니다.1개의 임시 테이블에는 로그인 레코드와 로그아웃 레코드가 포함됩니다.각 "누락" 필드는 NULL로 설정됩니다.

그런 다음 WIEGANDID를 사용하여 이들 테이블을 서로 결합할 수 있습니다.COALESCE는 늘 값이 필터링되고 올바른 값을 포함하는 다른 임시 테이블의 값으로 대체되도록 합니다.DATE_ 체크TIME_OUT은 DATE_보다 커야 합니다.TIME_IN은 해당 워커가 아직 로그아웃하지 않은 경우 DATE_OUT 및 TIME_OUT을 비워 둡니다.

결과 테이블에 HOWS_WORKED라는 새로운 컬럼을 추가했습니다.변동 시간으로 작업한 시간이 포함되어 있습니다.아직 종료되지 않은 시프트는 결과 세트에서 무시됩니다(HOURS_WORKED <> ").중복을 배제하고 복잡함을 회피하기 위해 HOURS_WORKED > 15의 결과 세트를 필터링합니다.이는 실제로는 발생하지 않고 보통 2교대 사이에 2교대 시간이 있기 때문에 2교대를 짧게 잡을 수 없기 때문입니다.일반적인 솔루션이 아니라 이 특정 애플리케이션에 적합한 솔루션입니다.

위 문장은 CREATE VIEW 문에서 사용할 수 있습니다.그런 다음 원래 테이블 대신 뷰를 사용하여 작업할 수 있으므로 복잡성을 줄일 수 있습니다.

아래 그림은 귀하의 모든 샘플 기록을 바탕으로 한 위의 쿼리 결과를 보여줍니다.여기에 이미지 설명 입력

나는 지난주에야 내 직원들의 펀치를 감시하는 앱을 만들었다.IN 및 PunchOUT 시간은 참석을 모니터링하는 데 소요되며, 따라서 데이터를 추가로 분석하기 위해 반나절이나 걸리는 휴가 등입니다.

제공된 데이터를 보고 분석 앱이 매우 단순해진 이유를 제안합니다.펀치에 타임스탬프 데이터 유형 사용IN과 Punch OUT을 사용하면 기존 열을 병합할 뿐만 아니라 작업 장애물을 제거할 수 있습니다.

IN 및 OUT 시간을 사용하여 "작업 시간"(단순 산술!)을 계산할 수 있습니다.플래그를 추가하여 야간 작업 여부(BETWIN 기능 사용) 등을 확인할 수 있습니다.바로 사용할 수 있는 심플한 기능으로 선도!

도움이 필요하시면 말씀해주세요...!

언급URL : https://stackoverflow.com/questions/52520904/how-to-select-records-into-a-single-record-to-determine-time-difference

반응형