11

これは私のテーブル(time_entries)のサンプル出力です

user_name| entry_type   | entry_datetime
 User1   |   Time In    | 28-JUL-13  16:40:40
 User1   |   Time Out   | 28-JUL-13  16:40:41
 User2   |   Time In    | 28-JUL-13  16:41:13
 User2   |   Time Out   | 28-JUL-13  16:41:15
 User1   |   Time In    | 27-JUL-13  16:42:30
 User1   |   Time Out   | 27-JUL-13  16:42:34
 User2   |   Time In    | 27-JUL-13  16:43:32
 User2   |   Time Out   | 27-JUL-13  16:43:35

今、私はこのクエリを使用しました

SELECT te.user_name, te.entry_name, MAX(te.entry_datetime) AS date
FROM time_entries AS te
GROUP BY te.entry_type, te.user_name

そして結果はこれです

user_name| entry_type   | entry_datetime
 User1   |   Time In    | 28-JUL-13  16:40:40
 User1   |   Time Out   | 28-JUL-13  16:40:41
 User2   |   Time In    | 28-JUL-13  16:41:13
 User2   |   Time Out   | 28-JUL-13  16:41:15

質問:同じ名前のユーザー名を 1 行にまとめる方法はありますか? このような出力があります。

user_name|  Date     | Timein   | Timeout
User1    | 28-JUL-13 | 16:40:40 | 16:40:41
User2    | 28-JUL-13 | 16:41:13 | 16:41:15

私はそれを行う方法について少し混乱しています。

4

5 に答える 5

6

私は次のようにアプローチします。

  1. 各ユーザーと日付の "time in" 時間を返すクエリを作成します。
  2. 各ユーザーと日付の「タイムアウト」時間を返す #1 のようなクエリを作成します。
  3. LEFT JOIN を使用して結果をマージします。

最終結果:

SELECT te.user_name, LEFT(te.entry_datetime, 10) AS entry_date, cin.entry_datetime AS timein, cout.entry_datetime AS timeout
FROM time_entries te
LEFT JOIN (SELECT user_name, LEFT(entry_datetime, 10) AS entry_date, MIN(entry_datetime) AS entry_datetime
    FROM time_entries
    WHERE entry_type = 'Time In'
    GROUP BY user_name, entry_date
) cin ON cin.user_name = te.user_name AND cin.entry_date = LEFT(te.entry_datetime, 9)
LEFT JOIN (SELECT user_name, LEFT(entry_datetime, 10) AS entry_date, MAX(entry_datetime) AS entry_datetime
    FROM time_entries
    WHERE entry_type = 'Time Out'
    GROUP BY user_name, entry_date
) cout ON cout.user_name = te.user_name AND cout.entry_date = LEFT(te.entry_datetime, 10)
GROUP BY te.user_name, entry_date;

デモ

ところで、LEFT()MySQL が理解できる実際の日付形式が列に含まれていないため、ここで使用しています。

于 2013-07-30T06:53:13.753 に答える
3

これはどうですか?

select
user_name,
date(entry_datetime) as date,
min(entry_datetime) as Timein,
max(entry_datetime) as Timeout
from (
  SELECT te.user_name, te.entry_name, MAX(te.entry_datetime) AS date
  FROM time_entries AS te
  GROUP BY te.entry_type, te.user_name) src
group by user_name, date
于 2013-07-30T06:12:36.847 に答える
1

これは仕事をします:

SELECT te.user_name,DATE(te.entry_datetime) as Date,te.entry_datetime AS TimeIn,te2.entry_datetime AS TimeOut
FROM time_entries te
JOIN time_entries te2 ON te.user_name=te2.user_name AND te2.entry_type="Time Out" AND
  te2.entry_datetime=
  (
    SELECT 
      entry_datetime
    FROM 
      time_entries
    WHERE entry_type='Time Out' AND user_name=te.user_name AND entry_datetime > te.entry_datetime
    ORDER BY 
      ABS(TIMESTAMPDIFF(SECOND, te.entry_datetime, `entry_datetime`))
    LIMIT 1
  )
WHERE te.entry_type="Time In";

編集:少し説明:

これは、user_name、日付部分、および TimeIn 部分の entry_datetime を選択します。次に、同じテーブルに結合して、タイムアウトの日時部分をフェッチします。これは、同じ user_name で Time In datetime に最も近い日付を持つ「Time Out」タイプのエントリを選択することによって行われます。

于 2013-07-30T06:29:32.297 に答える
1

これは、データを処理する方法に関するphp側のソリューションです。

function transformArray($data) {
   $final = array();
   foreach ($data as $key => $row) {
      if (!isset($final[$row['u']])) $final[$row['u']] = array('user' => $row['u']);
      $final[$row['u']][$row['t']] = date("H:i:s", strtotime($row['entrydatetime']));
      $final[$row['u']]['date'] = date("d:M:y", strtotime($row['entrydatetime']));
   }

   return $final;
}

このようなデータセットを渡すことができ、フィールド名を必要に応じて調整できます。

$data = array(
         array('u' => 'user1', 't' => 'TimeIn', 'entrydatetime' => '28-JUL-13  16:40:40'),
         array('u' => 'user1', 't' => 'TimeOut', 'entrydatetime' => '28-JUL-13  16:40:40'),
         array('u' => 'user2', 't' => 'TimeIn', 'entrydatetime' => '28-JUL-13  16:40:40'),
         array('u' => 'user2', 't' => 'TimeOut', 'entrydatetime' => '28-JUL-13  16:40:40')
);
于 2013-07-30T06:29:25.017 に答える