Enige tijd geleden ben ik helemaal vastgelopen op een bepaalde query, welke ik niet voor elkaar krijg.
Na gisteren een hele dag gestoeid en ge-Googled te hebben, ben ik inmiddels een paar stapjes dichterbij. Ik heb echter nog het laatste duwtje nodig....
Probleembeschrijving:
Ik heb een object dat kan worden gereserveerd. Een gebruiker heeft maximaal één object en dat object kan een X aantal (object.amount) keer worden gereserveerd. Ook kan de gebruiker vooraf opgeven op welke datums het object beschikbaar is (object.start / object.end). Beschikbaarheid en reserveringen worden gedaan in blokken van 30 minuten.
Nu wil ik uit de data kunnen halen welk object in een bepaalde periode nog gereserveerd kan worden en de beschikbaarheid (available in onderstaande query) groter is dan 0.
Een exportje van mijn test db:
De query die ik nu nog gebruik maar niet werkt:
In bovenstaande query gebruik ik overigens geen BETWEEN omdat in mijn situatie de eind tijd eigenlijk loopt tot :59 of :29.
Als bovenstaande query wordt uitgevoerd dan krijg je terug: available = 0, voor de periode van 12:00 tot 18:00. Terwijl het object eigenlijk nog 1x beschikbaar is. Dit heeft te maken met de overlap. Op het moment dat twee boekingen elkaar niet overlappen telt deze eigenlijk maar voor één boeking.
Op http://stackoverflow.com/...nt-calls-in-a-time-period heb ik een gelijksoortig probleembeschrijving gevonden. Ook zijn ASCII-weergave van het probleem is misschien duidelijker. Echter de gegeven oplossingen daar krijg ik niet aan de praat in mijn situatie. Ook probeer ik de oplossingen gegeven op http://stackoverflow.com/...ative-sum-column-in-mysql erbij te betrekken. Maar het lukt me maar niet.
Ik heb inmiddels dit:
In de kolom 'rt' wordt volgens mij alleen de vorige row waarde gebruikt. Wat nu de volgende waardes oplevert:
De kolom 'rt' lijkt alleen te kijken naar de vorige rij maar ik wil dat hij doorrekent, zodat ik vervolgens via MAX(rt) kan zien wat de maximale bezetting tijdens een periode is.
Wat ik wil zien is dus eigenlijk:
Iemand die mij de laatste zet kan geven?
Na gisteren een hele dag gestoeid en ge-Googled te hebben, ben ik inmiddels een paar stapjes dichterbij. Ik heb echter nog het laatste duwtje nodig....
Probleembeschrijving:
Ik heb een object dat kan worden gereserveerd. Een gebruiker heeft maximaal één object en dat object kan een X aantal (object.amount) keer worden gereserveerd. Ook kan de gebruiker vooraf opgeven op welke datums het object beschikbaar is (object.start / object.end). Beschikbaarheid en reserveringen worden gedaan in blokken van 30 minuten.
Nu wil ik uit de data kunnen halen welk object in een bepaalde periode nog gereserveerd kan worden en de beschikbaarheid (available in onderstaande query) groter is dan 0.
Een exportje van mijn test db:
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| CREATE TABLE IF NOT EXISTS `object` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `amount` int(11) NOT NULL, `start` datetime NOT NULL, `end` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; INSERT INTO `object` (`id`, `name`, `amount`, `start`, `end`) VALUES (1, 'Voorwerp 1', 3, '2015-07-12 12:00:00', '2015-07-12 18:00:00'), (2, 'Voorwerp 2', 4, '2015-07-12 10:00:00', '2015-07-12 15:00:00'); CREATE TABLE IF NOT EXISTS `reservation` ( `id` int(11) NOT NULL AUTO_INCREMENT, `object_id` int(11) NOT NULL, `start` datetime NOT NULL, `end` datetime NOT NULL, `status` tinyint(1) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ; INSERT INTO `reservation` (`id`, `object_id`, `start`, `end`, `status`) VALUES (1, 1, '2015-07-12 14:00:00', '2015-07-12 15:00:00', 1), (2, 1, '2015-07-12 12:00:00', '2015-07-12 17:30:00', 1), (3, 1, '2015-07-12 16:00:00', '2015-07-12 17:30:00', 1), (4, 1, '2015-07-12 12:00:00', '2015-07-12 12:30:00', 1); |
De query die ik nu nog gebruik maar niet werkt:
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| SELECT GROUP_CONCAT(r.id) reservations_ids, o.amount total, SUM(CASE WHEN r.id IS NOT NULL THEN 1 ELSE 0 END) total_reservations, (o.amount - SUM(CASE WHEN r.id IS NOT NULL THEN 1 ELSE 0 END)) available FROM object o LEFT JOIN reservation r ON r.object_id = o.id /* Only join reservations that are within the object availability */ AND (r.start >= o.start AND r.end < o.end) /* Only join reservations that are made for the given datetimes */ AND ( /* where given start date is between start and end */ ('2015-07-12 14:00' >= r.start AND '2015-07-12 14:00' < r.end) OR /* or where given end date is between start and end */ ('2015-07-12 17:00' >= r.start AND '2015-07-12 17:00' < r.end) OR /* or where given start date is smaller than start and given end date is bigger than end. */ ('2015-07-12 14:00' <= r.start AND '2015-07-12 17:00' > r.end) ) AND r.status = 1 WHERE 1=1 /* Check if object is available at all */ AND o.start <= '2015-07-12 14:00' AND o.end >= '2015-07-12 17:00' |
In bovenstaande query gebruik ik overigens geen BETWEEN omdat in mijn situatie de eind tijd eigenlijk loopt tot :59 of :29.
Als bovenstaande query wordt uitgevoerd dan krijg je terug: available = 0, voor de periode van 12:00 tot 18:00. Terwijl het object eigenlijk nog 1x beschikbaar is. Dit heeft te maken met de overlap. Op het moment dat twee boekingen elkaar niet overlappen telt deze eigenlijk maar voor één boeking.
Op http://stackoverflow.com/...nt-calls-in-a-time-period heb ik een gelijksoortig probleembeschrijving gevonden. Ook zijn ASCII-weergave van het probleem is misschien duidelijker. Echter de gegeven oplossingen daar krijg ik niet aan de praat in mijn situatie. Ook probeer ik de oplossingen gegeven op http://stackoverflow.com/...ative-sum-column-in-mysql erbij te betrekken. Maar het lukt me maar niet.
Ik heb inmiddels dit:
SQL:
1
2
3
4
5
6
7
8
9
10
11
| SELECT date, x.t, @runtot := (@runtot + x.t) AS rt, @runtot := x.t AS ne FROM (SELECT (@runtot := 0)) c, ( SELECT start AS date, 1 as t FROM reservation r WHERE start BETWEEN '2015-07-12 12:00:00' AND '2015-07-12 18:00:00' UNION ALL SELECT end AS date, -1 as t FROM reservation r WHERE end BETWEEN '2015-07-12 12:00:00' AND '2015-07-12 18:00:00' ORDER BY date ) x |
In de kolom 'rt' wordt volgens mij alleen de vorige row waarde gebruikt. Wat nu de volgende waardes oplevert:
code:
1
2
3
4
5
6
7
8
9
| date t rt ne 2015-07-12 12:00:00 1 1 1 2015-07-12 12:00:00 1 2 1 2015-07-12 12:30:00 -1 0 -1 2015-07-12 14:00:00 1 0 1 2015-07-12 15:00:00 -1 0 -1 2015-07-12 16:00:00 1 0 1 2015-07-12 17:30:00 -1 0 -1 2015-07-12 17:30:00 -1 -2 -1 |
De kolom 'rt' lijkt alleen te kijken naar de vorige rij maar ik wil dat hij doorrekent, zodat ik vervolgens via MAX(rt) kan zien wat de maximale bezetting tijdens een periode is.
Wat ik wil zien is dus eigenlijk:
code:
1
2
3
4
5
6
7
8
9
| date t rt ne 2015-07-12 12:00:00 1 1 1 2015-07-12 12:00:00 1 2 1 2015-07-12 12:30:00 -1 1 -1 2015-07-12 14:00:00 1 2 1 2015-07-12 15:00:00 -1 1 -1 2015-07-12 16:00:00 1 2 1 2015-07-12 17:30:00 -1 1 -1 2015-07-12 17:30:00 -1 0 -1 |
Iemand die mij de laatste zet kan geven?