2016-09-10 5 views
2

私はGROUP BY句を持つクエリを持っています。このクエリでは、recordsテーブルから従業員が「チェックイン」し、フィールドがの場合、従業員はオフィスにいますが、の場合、退職します。特定の列の最後の行の値(日付)を取得するためにGROUP BYを取得するにはどうすればよいですか?

GROUP BY節にrecords.dnと書いておきます。これは、従業員ごとに重複したエントリを作成することになります(名前をテーブル内で順番に2回取得します)。

私は選択でMINとMAXを使ってみましたが、それは全く意味がありませんでした。

従業員が複数回チェックイン/チェックアウトできるデータベースの複数の行から、LATEST行を取得してそのdnフィールドを使用するにはどうすればよいですか?

select 
    MAX(records.dn), 
    `records`.`din`, 
    `users`.`username`, 
    `users`.`id` as `user_id`, 
    DATE(records.created_at) AS date, 
    TIME(MIN(records.created_at)) AS first_log, 
    TIME(MAX(records.created_at)) AS last_log 
from `records` 
inner join `users` on `records`.`din` = `users`.`din` 
where records.created_at BETWEEN '2016-09-05 00:00:00' 
    AND '2016-09-08 00:00:00' 
group by `users`.`username`, DATE(records.created_at) 
order by `first_log` asc 

(第1の選択列がMAXを使用して、私がしようとしたものです)

これは、いくつかのサンプルデータを持つレコードのテーブルです:

これは私が話しているクエリは次のとおりです。

the table

どのように私は私が探しているものを達成できますか?

+0

私は昨日この状況にいました。私が見つけた最良の解決策はここにありますhttp://stackoverflow.com/questions/1313120/retrieving-the-last-record-in-each-group/1313293#1313293 –

+1

あなたの期待される結果は? sqlfiddleは誰の心を壊すことはありません:p – Drew

+0

http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be- a-very-simple-sql-query – Strawberry

答えて

1

substring_index()/group_concat()トリックは正確に何をしたい行う可能性があります:

select substring_index(group_concat(r.dn order by created_at desc), ',', 1) as last_dn, 
     u.username, u.id as `user_id`, 
     DATE(r.created_at) AS date, 
     TIME(MIN(r.created_at)) AS first_log, 
     TIME(MAX(r.created_at)) AS last_log 
from records r inner join 
    users u 
    on r.din = u.din 
where r.created_at >= '2016-09-05' and 
     r.created_at < '2016-09-08' 
group by u.username, DATE(r.created_at) 
order by first_log asc; 

書かれたように、これは3つの制約があります。

  1. それはdnがそれにカンマを持っていないことを前提として(別のセパレータを使用して簡単に修正できます)。
  2. ユーザーの1日のdnのリストは、group_concat()の文字列の最大長を超えないものとします。これは、システムパラメータを使用して調整することもできます。
  3. last_dnは、元のタイプではなくても文字列です。

しかし、このトリックはほとんどの場合よく機能します。パラメータgroup_concat_max_lenは中間文字列のサイズです。デフォルト(described)は1,024です。これは、最大100個以上の整数に対しては問題ありません。これはセッションパラメータであり、簡単に変更できます。

  • 私は、クエリ内の不要なバッククォートはちょうどそれが困難読むために作ると思う:

    また、次の変更に注意してください。

  • テーブルエイリアスを使用すると、クエリの書き込みと読み取りが容易になります。
  • betweenは、包括的であるとは思いません。私はあなたが8日前に厳密に日付/時刻値を求めていると思います。
+0

答えをありがとう、私はまもなくそれを試してみるつもりです。私がそれをする前に、ちょうど質問と明確化... 'group_concat()'の最大長は?これはLaravelが出力したクエリなので、フレームワークはそれだけでチックを追加します。ここでコピーしました:)。日付との間の 'between'節も動的です - 私はdaterange pickerのためにそれを必要とします。 – Aborted

+0

SQLSTATE [42000]:構文エラーまたはアクセス違反:1064 SQL構文にエラーがあります。あなたのMySQLサーバのバージョンに対応するマニュアルを見て、適切な構文が '' records'.'din'、 'users'.'username'、' users'.'id''を 'user_id'、DATE(レコード。 (SQL:select substring_index(group_concat(records.dn order by created_at desc))、 'records'.'din'、' users'.'username'、 'users'.'id''を' user_id'として選択します。 、日付(TIME(MIN(records.created_at))をfirst_log、時刻(MAX(records.created_at)) – Aborted

+0

をlast_logとして 'records'内部結合' users'を 'records'.'din '=' users'.'din'ここで、'2016-09-05 00:00:00 'と' 2016-09-08 00:00:00 'の間の 'users'.'username'によるrecords.created_at、DATE (records.created_at)order by 'first_log' asc) – Aborted

関連する問題