1

次のようなmysqlのテーブルがあります。

+------------+------------+------------+------------+ 
|     date   |   user_id  | start_hour | end_hour   | 
+------------+------------+------------+------------+ 
| 2010-12-15 |         20 | 08:00:00   | 08:15:00   | 
| 2010-12-15 |         20 | 14:00:00   | 14:30:00   | 
| 2010-12-15 |         20 | 17:00:00   | 17:45:00   | 
+------------+------------+------------+------------+ 

ここで見つけたユーザーの時間の時間範囲と例を抽出しようとしましたが、時間でそれを機能させることはできません

私はクエリを試しました:

 $sql="
SELECT a.end_hour AS 'Available From', Min(b.start_hour) AS 'To' 

FROM ( 
SELECT  0 as date, '08:00:00' as start_hour,'08:00:00' as end_hour 
UNION SELECT date, start_hour, end_hour FROM table
) 

AS a JOIN 
( SELECT  date, start_hour, end_hour  FROM table 
UNION SELECT 0,  '21:00:00' as start_hour, '22:00:00' as end_hour
) AS b ON

a.date=b.date AND  a.user_id=b.user_id AND a.end_hour < b.start_hour WHERE  
a.date='$date'  AND a.user_id='$user_id' GROUP BY a.end_hour 
HAVING a.end_hour < Min(b.start_hour);"; 

08:00 から 21:00 までの範囲を作成し、次のような予定の間に空きブロックを作成する必要があります。

free time
08:15:00 to 14:00:00
14:30:00 to 17:00:00
17:45:00 to 21:00:00
4

4 に答える 4

2

このクエリを試してください

SELECT
  a.id,
  a.start_hour,
  a.end_hour,
  TIMEDIFF(la.start_hour, a.end_hour) as `Free Time`
FROM appointment as a
  LEFT JOIN(SELECT * FROM appointment LIMIT 1,18446744073709551615) AS la
    ON la.id = a.id + 1
  LEFT JOIN (SELECT * FROM appointment) AS ra ON a.id = ra.id

これにより、これらの結果が表示されます

+---------------------------------------------+
¦ id ¦ start_hour BY ¦ end_hour   | Free Time |
¦----+---------------¦------------------------|
¦  1 ¦   08:00:00    ¦  08:15:00  | 05:45:00  |
¦  2 ¦   14:00:00    ¦  14:30:00  | 02:30:00  |
¦  3 ¦   17:00:00    ¦  17:45:00  | 03:15:00  |
¦  4 ¦   21:00:00    ¦  21:00:00  | (NULL)    |
+--------------------+------------------------+ 

また、テーブルに 21:00:00 が含まれている必要があります。そうしないと、最後の時差を取得できません。テーブルの開始日と終了日として 21:00:00 を入力しました。

編集済み

これは変更されたクエリです

SELECT
  a.id,
  a.end_hour AS `Free time Start`,
  IFNULL(la.start_hour,a.end_hour) AS `Free Time End`,
  IFNULL(TIMEDIFF(la.start_hour, a.end_hour),'00:00:00') AS `Total Free Time`
FROM appointment AS a
  LEFT JOIN (SELECT * FROM appointment LIMIT 1,18446744073709551615) AS la
    ON la.id = (SELECT MIN(id) FROM appointment where id > a.id LIMIT 1)      

そして結果は

+--------------------------------------------------------+
¦ id ¦ Free time Start ¦ Free Time End | Total Free Time |
¦----+-----------------¦---------------------------------|
¦  1 ¦   08:15:00      ¦ 14:00:00      |    05:45:00     |
¦  2 ¦   14:30:00      ¦ 17:00:00      |    02:30:00     |
¦  3 ¦   17:45:00      ¦ 21:00:00      |    03:15:00     |
¦  4 ¦   21:00:00      ¦ 21:00:00      |    00:00:00     |
+----------------------+---------------------------------+  

このクエリから学ぶポイントは次のとおりです。

  1. Timediff 関数の使用。timediff('終了時間','開始時間')
  2. 上位番号での参加
  3. ゼロではなく 1 から始まる長いオフセットと制限を持つ結合の最初のレコードを避ける
  4. IFNULL の使用方法 ifnull('ここに null がある場合','これを選択')
于 2012-06-29T13:53:04.447 に答える
1

このクエリを試してみてください。うまくいくことを願っています.....

SELECT
  a.id,
  a.end_hour    AS `Free time Start`,
  la.start_hour AS `Free Time End`,
  IFNULL(TIMEDIFF(la.start_hour, a.end_hour),'00:00:00') AS `Total Free Time`
FROM appointment AS a
  LEFT JOIN (SELECT *
             FROM appointment
             LIMIT 1,18446744073709551615) AS la
    ON la.id = (SELECT
                  id
                FROM appointment
                WHERE id NOT IN(a.id)
                ORDER BY (a.id > id)ASC
                LIMIT 1);
于 2012-06-29T15:24:33.297 に答える
0

これにより、終了時間ブロックが得られます

SELECT T_a.end_hour
FROM (table AS T_a) LEFT JOIN (table AS T_b)
ON (T_a.`date`=T_b.`date` AND T_b.start_hour<=T_a.end_hour AND T_b.end_hour>T_a.end_hour)
WHERE T_b.user_id IS NULL

これにより、開始時間ブロックが得られます

SELECT T_a.start_hour
FROM (table AS T_a) LEFT JOIN (table AS T_b)
ON (T_a.`date`=T_b.`date` AND T_b.start_hour<T_a.start_hour AND T_b.end_hour>=T_a.start_hour)
WHERE T_b.user_id IS NULL

これらのクエリは、交差していない、または他のスロットに突き合わされている開始または終了を探します。したがって、10-11 11-12 は 10 開始、12 終了 = 自由時間は 08-10 と 12-21 になります

したがって、自由時間は 08:00 (開始時間でない限り) から最初の「開始」時間までで、END->START から最後の END->21:00 までのペアが一致します (21:00 が最後の終了でない限り)

注意: 日付も追加する必要があります。

于 2012-06-29T13:20:14.447 に答える
0

おそらくこれはオーバーキルですが、これは sql-server で動作します。mysql に変換する努力は確かではありません

declare @AvailableTime table ( AvailableDate date,  StartTime time, EndTime time )

insert into @AvailableTime values 
('15 dec 2010', '08:00:00', '21:00:00')

declare @Booking table (BookingDate date, UserId int, StartTime Time, EndTime Time)

insert into @Booking values 
('15 dec 2010', 20, '08:00:00', '08:15:00'),
('15 dec 2010', 20, '14:00:00', '14:30:00'),
('15 dec 2010', 20, '17:00:00', '17:45:00')

select 
    *
from
(
    -- first SELECT get start boundry
    select t.StartTime s, b.StartTime e
    from @AvailableTime t, @Booking b
    where 
        t.AvailableDate = b.BookingDate and (t.StartTime <= b.EndTime and b.StartTime <= t.EndTime) and t.StartTime <> b.StartTime
    and
        not exists (select 1 from @Booking b2 where b2.BookingDate = b.BookingDate and b2.StartTime < b.StartTime)

    union

    -- second SELECT get spikes ie middle
    select b1.EndTime s, b2.StartTime e
    from @AvailableTime t, @Booking b1, @Booking b2
    where 
        t.AvailableDate = b1.BookingDate and (t.StartTime <= b1.EndTime and b1.StartTime <= t.EndTime) 
    and 
        t.AvailableDate = b2.BookingDate and (t.StartTime <= b2.EndTime and b2.StartTime <= t.EndTime) 
    and 
        b1.EndTime < b2.StartTime
    and
        not exists (select 1 from @Booking b3 where b3.BookingDate = t.AvailableDate and b3.StartTime > b1.EndTime and b3.EndTime < b2.StartTime)

    union

    -- third SELECT get end boundry
    select b.EndTime s, t.EndTime e
    from @AvailableTime t, @Booking b
    where 
        t.AvailableDate = b.BookingDate and (t.StartTime <= b.EndTime and b.StartTime <= t.EndTime) and t.EndTime <> b.EndTime
    and 
        not exists (select 1 from @Booking b2 where b2.BookingDate = b.BookingDate and b2.StartTime > b.StartTime)
) t1
于 2012-06-29T13:50:19.687 に答える