복붙노트

[SQL] 사용자 당 가장 최근 날짜를 선택 행

SQL

사용자 당 가장 최근 날짜를 선택 행

나는 사용자의 체크인과 아웃 시간 ( "lms_attendance")이 같다고 테이블이 있습니다

id  user    time    io (enum)
1   9   1370931202  out
2   9   1370931664  out
3   6   1370932128  out
4   12  1370932128  out
5   12  1370933037  in

내가 좋아하는 뭔가 때문에, 사용자 ID 당 가장 최근의 기록겠습니까 출력, 동안 나에게 값 "밖으로" "의"나주는 것이이 테이블의 뷰를 만들려고 해요 :

id  user    time    io
2   9   1370931664  out
3   6   1370932128  out
5   12  1370933037  in

지금까지 아주 가까이,하지만 난 뷰가 많이 어렵게하고있다 하위 쿼리를 수락하지 않습니다 것을 깨달았다. 가장 가까운 쿼리 I의 GOT했다 :

select 
    `lms_attendance`.`id` AS `id`,
    `lms_attendance`.`user` AS `user`,
    max(`lms_attendance`.`time`) AS `time`,
    `lms_attendance`.`io` AS `io` 
from `lms_attendance` 
group by 
    `lms_attendance`.`user`, 
    `lms_attendance`.`io`

하지만 내가 할 것은 :

id  user    time    io
3   6   1370932128  out
1   9   1370931664  out
5   12  1370933037  in
4   12  1370932128  out

어떤 가까이,하지만 완벽하지. 나는에 의해 마지막 그룹이 존재하지 않아야 알고 있지만, 그것없이, 그것은 가장 최근의 시간을 반환합니다,하지만 그것은 상대 IO 값이다와.

어떤 아이디어? 감사!

해결법

  1. ==============================

    1.질문:

    질문:

    SQL 뿐인 예

    SELECT t1.*
    FROM lms_attendance t1
    WHERE t1.time = (SELECT MAX(t2.time)
                     FROM lms_attendance t2
                     WHERE t2.user = t1.user)
    

    결과:

    | ID | USER |       TIME |  IO |
    --------------------------------
    |  2 |    9 | 1370931664 | out |
    |  3 |    6 | 1370932128 | out |
    |  5 |   12 | 1370933037 |  in |
    

    솔루션 거 작업마다 :

    SQL 뿐인 예

    SELECT t1.*
    FROM lms_attendance t1
    WHERE t1.id = (SELECT t2.id
                     FROM lms_attendance t2
                     WHERE t2.user = t1.user            
                     ORDER BY t2.id DESC
                     LIMIT 1)
    
  2. ==============================

    2.이 같은 바퀴 되곤을 시도 할 필요는 일반적인 큰-N-그룹 별 문제가 없다. 아주 좋은 솔루션이 제공됩니다.

    이 같은 바퀴 되곤을 시도 할 필요는 일반적인 큰-N-그룹 별 문제가 없다. 아주 좋은 솔루션이 제공됩니다.

    나는 (이렇게 쉬운 뷰에서 사용) 서브 쿼리없이 (SQLFiddle를 참조 저스틴의 업데이트) 가장 간단한 솔루션을 선호 :

    SELECT t1.*
    FROM lms_attendance AS t1
    LEFT OUTER JOIN lms_attendance AS t2
      ON t1.user = t2.user 
            AND (t1.time < t2.time 
             OR (t1.time = t2.time AND t1.Id < t2.Id))
    WHERE t2.user IS NULL
    

    (t1.time = t2.time 및 t1.Id

  3. ==============================

    3.하위 쿼리에 대한 필요가 없기 때문에 @TMS에 본사를 둔 그것을처럼, 나는 대답하지만 난 'OR'부분은 충분할 것이다 ommiting 이해하고 읽을 훨씬 간단하게 생각합니다.

    하위 쿼리에 대한 필요가 없기 때문에 @TMS에 본사를 둔 그것을처럼, 나는 대답하지만 난 'OR'부분은 충분할 것이다 ommiting 이해하고 읽을 훨씬 간단하게 생각합니다.

    SELECT t1.*
    FROM lms_attendance AS t1
    LEFT JOIN lms_attendance AS t2
      ON t1.user = t2.user 
            AND t1.time < t2.time
    WHERE t2.user IS NULL
    

    당신이 널 시간이 행에 관심이없는 경우는 WHERE 절에를 필터링 할 수 있습니다 :

    SELECT t1.*
    FROM lms_attendance AS t1
    LEFT JOIN lms_attendance AS t2
      ON t1.user = t2.user 
            AND t1.time < t2.time
    WHERE t2.user IS NULL and t1.time IS NOT NULL
    
  4. ==============================

    4.이미 해결하지만, 단지 기록을 위해, 또 다른 방법은 두 가지 뷰를 생성하는 것입니다 ...

    이미 해결하지만, 단지 기록을 위해, 또 다른 방법은 두 가지 뷰를 생성하는 것입니다 ...

    CREATE TABLE lms_attendance
    (id int, user int, time int, io varchar(3));
    
    CREATE VIEW latest_all AS
    SELECT la.user, max(la.time) time
    FROM lms_attendance la 
    GROUP BY la.user;
    
    CREATE VIEW latest_io AS
    SELECT la.* 
    FROM lms_attendance la
    JOIN latest_all lall 
        ON lall.user = la.user
        AND lall.time = la.time;
    
    INSERT INTO lms_attendance 
    VALUES
    (1, 9, 1370931202, 'out'),
    (2, 9, 1370931664, 'out'),
    (3, 6, 1370932128, 'out'),
    (4, 12, 1370932128, 'out'),
    (5, 12, 1370933037, 'in');
    
    SELECT * FROM latest_io;
    

    SQL 바이올린의 행동을 보려면 여기를 클릭하십시오

  5. ==============================

    5.

    select b.* from 
    
        (select 
            `lms_attendance`.`user` AS `user`,
            max(`lms_attendance`.`time`) AS `time`
        from `lms_attendance` 
        group by 
            `lms_attendance`.`user`) a
    
    join
    
        (select * 
        from `lms_attendance` ) b
    
    on a.user = b.user
    and a.time = b.time
    
  6. ==============================

    6.

     select result from (
         select vorsteuerid as result, count(*) as anzahl from kreditorenrechnung where kundeid = 7148
         group by vorsteuerid
     ) a order by anzahl desc limit 0,1
    
  7. ==============================

    7.좋아,이 해킹 또는 오류가 발생하기 쉬운,하지만 어떻게 든이 잘대로 작동이 될 수 있습니다

    좋아,이 해킹 또는 오류가 발생하기 쉬운,하지만 어떻게 든이 잘대로 작동이 될 수 있습니다

    SELECT id, MAX(user) as user, MAX(time) as time, MAX(io) as io FROM lms_attendance GROUP BY id;
    
  8. ==============================

    8.만약 당신의 MySQL 8.0에 이상이 윈도우 기능을 사용할 수 있습니다 :

    만약 당신의 MySQL 8.0에 이상이 윈도우 기능을 사용할 수 있습니다 :

    질문:

    DB 바이올린 예

    SELECT DISTINCT
    FIRST_VALUE(ID) OVER (PARTITION BY lms_attendance.USER ORDER BY lms_attendance.TIME DESC) AS ID,
    FIRST_VALUE(USER) OVER (PARTITION BY lms_attendance.USER ORDER BY lms_attendance.TIME DESC) AS USER,
    FIRST_VALUE(TIME) OVER (PARTITION BY lms_attendance.USER ORDER BY lms_attendance.TIME DESC) AS TIME,
    FIRST_VALUE(IO) OVER (PARTITION BY lms_attendance.USER ORDER BY lms_attendance.TIME DESC) AS IO
    FROM lms_attendance;
    

    결과:

    | ID | USER |       TIME |  IO |
    --------------------------------
    |  2 |    9 | 1370931664 | out |
    |  3 |    6 | 1370932128 | out |
    |  5 |   12 | 1370933037 |  in |
    

    나는 저스틴에 의해 제안 된 솔루션을 사용을 통해 볼 수있는 장점은 중간 뷰 또는 테이블의 필요없이, 심지어 하위 쿼리에서 가장 최근의 데이터를 사용자 당 (또는 ID 당, 또는 무엇이든 당)과 행을 선택 할 수 있다는 것입니다.

    그리고 경우에 귀하는 HANA를 실행 그것은 ~ 7 배 빠른 또한 : D

  9. ==============================

    9.이 쿼리 검색 :

    이 쿼리 검색 :

      select id,user, max(time), io 
      FROM lms_attendance group by user;
    
  10. ==============================

    10.아마도 당신은 시간의 내림차순으로 사용자가 다음 순서로 그룹을 할 수 있습니다. 아래와 같은 뭔가

    아마도 당신은 시간의 내림차순으로 사용자가 다음 순서로 그룹을 할 수 있습니다. 아래와 같은 뭔가

      SELECT * FROM lms_attendance group by user order by time desc;
    
  11. ==============================

    11.이것은 나를 위해 일한 :

    이것은 나를 위해 일한 :

    SELECT user, time FROM 
    (
        SELECT user, time FROM lms_attendance --where clause
    ) AS T 
    WHERE (SELECT COUNT(0) FROM table WHERE user = T.user AND time > T.time) = 0
    ORDER BY user ASC, time DESC
    
  12. from https://stackoverflow.com/questions/17038193/select-row-with-most-recent-date-per-user by cc-by-sa and MIT license