150

次のようなユーザーのチェックイン時間とチェックアウト時間の表 (「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

「in」または「out」の値を与えながら、ユーザーIDごとに最新のレコードのみを出力するこのテーブルのビューを作成しようとしています。

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

これまでのところかなり近づいていますが、ビューがサブクエリを受け入れないことに気付きました。これが非常に難しくなっています。私が得た最も近いクエリは次のとおりです。

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

これは近いですが、完璧ではありません。最後の group by があってはならないことはわかっていますが、それがないと、最新の時刻が返されますが、相対 IO 値は返されません。

何か案は?ありがとう!

4

13 に答える 13

239

クエリ:

SQLFIDDLE例

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 |

ユーザーが同じ「最大」時間の複数のレコードを持っている場合、上記のクエリは複数のレコードを返すことに注意してください。ユーザーごとに 1 つのレコードのみが必要な場合は、次のクエリを使用します。

SQLFIDDLE例

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)
于 2013-06-11T07:22:09.080 に答える
6

@TMSの回答に基づいて、サブクエリは必要ないので気に入っていますが、その'OR'部分を省略すれば十分であり、理解しやすく読みやすいと思います。

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

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
于 2016-03-11T18:07:53.847 に答える
5

すでに解決されていますが、記録のために、別のアプローチは2つのビューを作成することです...

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 Fiddle での動作を確認してください

于 2013-06-11T07:30:50.030 に答える
0
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
于 2013-06-11T07:18:18.573 に答える
0

私は私のために働く1つの解決策を試しました

    SELECT user, MAX(TIME) as time
      FROM lms_attendance
      GROUP by user
      HAVING MAX(time)
于 2021-12-22T11:27:37.233 に答える
-3

おそらく、ユーザーごとにグループ化してから、時間の説明で並べ替えることができます。以下のようなもの

  SELECT * FROM lms_attendance group by user order by time desc;
于 2013-06-11T07:17:03.273 に答える