Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Here's a solution that seems to work:</p> <pre><code>SELECT t.*, DATEDIFF(t.LatestAvailable, t.EarliestAvailable) AS LengthAvailable FROM (SELECT u.*, COALESCE(b1.End, @StartOfWindow) AS EarliestAvailable, COALESCE(b2.Start, @EndOfWindow) AS LatestAvailable FROM LettingUnits u LEFT OUTER JOIN LettingUnitBookings b1 ON (u.ID = b1.F_LU_ID AND b1.End BETWEEN @StartOfWindow AND @EndOfWindow) LEFT OUTER JOIN LettingUnitBookings b2 ON (u.ID = b2.F_LU_ID AND b2.Start BETWEEN @StartOfWindow AND @EndOfWindow AND b2.Start &gt;= b1.End) -- edit: new term ) AS t LEFT OUTER JOIN LettingUnitBookings x ON (t.ID = x.F_LU_ID AND x.Start &lt; t.LatestAvailable AND x.End &gt; t.EarliestAvailable) WHERE x.ID IS NULL AND DATEDIFF(t.LatestAvailable, t.EarliestAvailable) &gt;= @WindowSize; </code></pre> <p>The output is:</p> <pre><code>+-----+-------------+-------------------+-----------------+-----------------+ | ID | Name | EarliestAvailable | LatestAvailable | LengthAvailable | +-----+-------------+-------------------+-----------------+-----------------+ | 123 | Foo Cottage | 2009-01-05 | 2009-01-10 | 5 | | 123 | Foo Cottage | 2009-01-20 | 2009-01-25 | 5 | | 456 | Bar Cottage | 2009-01-20 | 2009-01-31 | 11 | +-----+-------------+-------------------+-----------------+-----------------+ </code></pre> <p>Analyzing this with <code>EXPLAIN</code> shows that it employs indexes pretty well:</p> <pre><code>+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+---------------+---------+---------+-------+------+-------------------------+ | 1 | PRIMARY | &lt;derived2&gt; | ALL | NULL | NULL | NULL | NULL | 9 | Using where | | 1 | PRIMARY | x | ref | F_LU_ID | F_LU_ID | 8 | t.ID | 2 | Using where; Not exists | | 2 | DERIVED | u | system | NULL | NULL | NULL | NULL | 1 | | | 2 | DERIVED | b1 | ref | F_LU_ID | F_LU_ID | 8 | const | 0 | | | 2 | DERIVED | b2 | ref | F_LU_ID | F_LU_ID | 8 | const | 0 | | +----+-------------+------------+--------+---------------+---------+---------+-------+------+-------------------------+ </code></pre> <p>Compare with the <code>EXPLAIN</code> report for the solution <a href="https://stackoverflow.com/questions/1687519/searching-for-availability-with-mysql-and-php/1691282#1691282">given</a> by @martin clayton:</p> <pre><code>+----+--------------+---------------------+--------+---------------+---------+---------+------+------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+--------------+---------------------+--------+---------------+---------+---------+------+------+---------------------------------+ | 1 | PRIMARY | lu | system | PRIMARY,ID | NULL | NULL | NULL | 1 | | | 1 | PRIMARY | &lt;derived2&gt; | ALL | NULL | NULL | NULL | NULL | 4 | Using where | | 2 | DERIVED | &lt;derived3&gt; | ALL | NULL | NULL | NULL | NULL | 4 | Using temporary; Using filesort | | 2 | DERIVED | &lt;derived5&gt; | ALL | NULL | NULL | NULL | NULL | 4 | Using where; Using join buffer | | 5 | DERIVED | LettingUnitBookings | ALL | NULL | NULL | NULL | NULL | 3 | | | 6 | UNION | LettingUnitBookings | index | NULL | F_LU_ID | 8 | NULL | 3 | Using index | | NULL | UNION RESULT | &lt;union5,6&gt; | ALL | NULL | NULL | NULL | NULL | NULL | | | 3 | DERIVED | LettingUnitBookings | ALL | NULL | NULL | NULL | NULL | 3 | | | 4 | UNION | LettingUnitBookings | index | NULL | F_LU_ID | 8 | NULL | 3 | Using index | | NULL | UNION RESULT | &lt;union3,4&gt; | ALL | NULL | NULL | NULL | NULL | NULL | | +----+--------------+---------------------+--------+---------------+---------+---------+------+------+---------------------------------+ </code></pre> <p>In general, you want to avoid optimization plans that force <code>Using filesort</code> or <code>Using temporary</code> because these are performance killers. A query using <code>GROUP BY</code> is almost certain to cause this kind of optimization, at least in MySQL.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload