2016-04-27 23 views
1

私はMySQLを使用しています。私は日付の間隔のグループの各間隔に属する予約の夜を取得しようとしています。しかし、いくつかの間隔が他のものより優先されるので、私はのためにできるだけ多くの夜をとり、好ましい間隔は**とし、ギャップは**好ましくない間隔**で埋めるでしょう。これを説明するために、私はそれをここに表示されます:=> 2016年1月16日MySQLの日付の選択間隔

チェックアウト=> 2016年2月8日

総夜で

チェック=:

は日付を考えます> 24

 Preferred | date_from | date_to | Nights  
---------------------------------------------------- 
    1   | 2016-01-15 | 2016-01-17 | 2 
    1   | 2016-02-03 | 2016-02-10 | 6 
    1   | 2016-01-20 | 2016-01-25 | 6 
    0   | 2016-01-20 | 2016-01-31 | 2 (2016-01-26 and 2016-01-31 because the other nights are covered by a preferred period) 
    1   | 2016-01-27 | 2016-01-30 | 4 
    0   | 2016-01-15 | 2016-01-17 | 0 (these dates are covered by a the first interval which is a preferred interval) 
    0   | 2016-02-01 | 2016-02-10 | 2 (just 2016-02-01 and 2016-02-02 because 03 - 08 are covered by the second interval which is a preferred interval) 
    0   | 2016-01-18 | 2016-01-19 | 2 

どのように私はこれをMySQLで達成できますか?

+0

03ので、同じように興味を持っている行のみを使用してサブクエリを絞り込むことができます大きすぎる - 08秒間隔OR 03で覆われています - 10 #typo – diEcho

+0

@diEcho私はそれがtypoだとは思わない03-08は第2の間隔でカバーされています09と10はチェックイン/チェックアウトの範囲外のため無視されます –

答えて

0

あなたがPreferred、date_from、date_toという列を持つテーブルを持っていて、あなたはただの数を計算しようとしていると仮定します。

このクエリを試すことができます。

SET @checkin = '2016-01-16'; 
SET @checkout = '2016-02-08'; 

SELECT T0.preferred,T0.date_from,T0.date_to,IFNULL(NIGHTS.nights,0) as Nights 
FROM YourTable T0 
LEFT JOIN 
    (SELECT T1.preferred,T1.date_from,T1.date_to,COUNT(*) AS Nights 
     FROM YourTable AS T1 
     INNER JOIN 
     (SELECT (@checkin + INTERVAL n DAY) as singleday 
     FROM numbers 
     WHERE (@checkin + INTERVAL n DAY) <= @checkout)DAYS1 
     ON DAYS1.singleday BETWEEN T1.date_from AND T1.date_to 
     WHERE T1.preferred = 1 
     OR NOT EXISTS 
     (SELECT 1 
     FROM YourTable AS T 
     WHERE T.preferred = 1 
     AND DAYS1.singleday BETWEEN T.date_from AND T.date_to 
     ) 
    GROUP BY T1.preferred,T1.date_from,T1.date_to 
    )NIGHTS 
ON T0.preferred = NIGHTS.preferred 
AND T0.date_from = NIGHTS.date_from 
AND T0.date_to = NIGHTS.date_to 
WHERE 
    T0.date_from <= @checkout 
AND T0.date_to >= @checkin 
; 

http://sqlfiddle.com/#!9/d64344/10 あなたは、実際のチェックインと@checkout@checkin出現を交換し、時間をチェックアウトすることができます。 、あなたの実際のテーブル名

私は、テーブルに滞在可能日数のどんな最大数に上向きにカウント0から番号を含む列nと呼ばれる番号が含まれているsqlfiddleにそうそうでYourTable発生を置き換えることができます。このテーブルも作成する必要があります。テーブル番号を作成する

CREATE TABLE numbers AS 
SELECT a.n+b.n+c.n+d.n+e.n+f.n+g.n+h.n+i.n as n 
FROM 
(SELECT 0 as n UNION SELECT 1)a, 
(SELECT 0 as n UNION SELECT 2)b, 
(SELECT 0 as n UNION SELECT 4)c, 
(SELECT 0 as n UNION SELECT 8)d, 
(SELECT 0 as n UNION SELECT 16)e, 
(SELECT 0 as n UNION SELECT 32)f, 
(SELECT 0 as n UNION SELECT 64)g, 
(SELECT 0 as n UNION SELECT 128)h, 
(SELECT 0 as n UNION SELECT 256)i; 
  • クエリの、について説明

1以下)サブクエリDAYS1範囲に

を@checkoutする@checkinからのすべての単一の日付 を返す使用します2)T1はDAYS1と結合されています。 が優先されているか、または優先行が存在しません。 ERS DAYS1の日付

3)その後、我々はDATE_TOは、単一の日

4の数を取得するには、 好ましく、DATE_FROM BY COUNT(*)GROUPを行う)その後、我々は、我々の結果NIGHTS

5呼び出します)その後、T0はNIGHTSでLEFT JOINEDされ、0の行を持つ偶数行を取得します。

6)@ checkin/@ checkout範囲を傍受するT0行のみを返します。

UPDATEあなたの表は、あなたがしようとすると、あなたがこの

SET @checkin = '2016-01-16'; 
SET @checkout = '2016-02-08'; 

SELECT T0.preferred,T0.date_from,T0.date_to,IFNULL(NIGHTS.nights,0) as Nights 
FROM (SELECT * FROM YourTable WHERE date_from <= @checkout AND date_to >= @checkin) T0 
LEFT JOIN 
    (SELECT T1.preferred,T1.date_from,T1.date_to,COUNT(*) AS Nights 
     FROM (SELECT * FROM YourTable WHERE date_from <= @checkout AND date_to >= @checkin) AS T1 
     INNER JOIN 
     (SELECT (@checkin + INTERVAL n DAY) as singleday 
     FROM numbers 
     WHERE (@checkin + INTERVAL n DAY) <= @checkout)DAYS1 
     ON DAYS1.singleday BETWEEN T1.date_from AND T1.date_to 
     WHERE T1.preferred = 1 
     OR NOT EXISTS 
     (SELECT 1 
     FROM (SELECT * FROM YourTable WHERE date_from <= @checkout AND date_to >= @checkin) AS T 
     WHERE T.preferred = 1 
     AND DAYS1.singleday BETWEEN T.date_from AND T.date_to 
     ) 
    GROUP BY T1.preferred,T1.date_from,T1.date_to 
    )NIGHTS 
ON T0.preferred = NIGHTS.preferred 
AND T0.date_from = NIGHTS.date_from 
AND T0.date_to = NIGHTS.date_to 
; 
+0

それは動作しますが、私のテーブルは多くの行を持っており、プロダクション環境では、 "YourTable"ビュー(例では、例を複雑にしないために省略した列が多いビュー)には何千もの行があります。しかし、このようなエレガントな方法で、例の解決策を思いついたのはすばらしいことです。ありがとうございます!! –

+0

それは –

+0

が再び私の答えをチェックしてください参加する開始する前に、それは私がそれを更新し、結果を絞り込むように、多分あなたは同様に、内側のクエリに 'WHERE DATE_FROM <= @checkout AND DATE_TO> = @ checkin'を追加最下位のクエリは、結果セットを絞り込む前に、そのクエリを使って何かをしようとします。 –

関連する問題