views:

74

answers:

1

There is one-2-many relation between Property and Reservation. Property has column called 'nr_of_bookings'. I need DQL that will retrieve only the properties that has COUNT(Reservation) less than Property.nr_of_bookins.

An example: Some Property has nr_of_bookings = 3 . If it has 5 Reservations related, it will not be retrieved. But if it has 2 related Reservations, it will be retrieved.

I tried numerous combinations, but I miss something obviosly. I posted similar question here , but it is better to start from scratch. Thanks.

+1  A: 

Have you tried:

'SELECT p FROM Product p WHERE SIZE(p.reservations) < p.nr_of_bookings'

EDIT: The above is for Doctrine 2. For Doctrine 1.2, looking at your code, I'm guessing your HAVING clause is referencing something that's not in a group by or the result of an aggregate function. Try something like this:

$q = PropertyTable::getInstance()
    ->createQuery('p') 
    ->select('p.*, COUNT(r.id) as num_of_reservations, SUM(p.nr_of_bookings) as num_bookings') 
    ->leftJoin('p.Reservation r') 
    ->groupBy('p.id') 
    ->having('num_of_reservations < num_bookings');

You're grouping by p.id so SUM(p.nr_of_bookings) will be equal to p.nr_bookings.

From the MySQL documentation:

The SQL standard does not permit the HAVING clause to name any column not found in the GROUP BY clause if it is not enclosed in an aggregate function.

rojoca
Basic DQL is like this:
Zeljko
$q = PropertyTable::getInstance()->createQuery('p') ->select('p.*, COUNT(r.id) as num_of_reservations') ->groupBy('p.id') ->leftJoin('p.Reservation r') ->having('num_of_reservations < p.nr_of_bookings') ; I would later add some extra conditions like: ->leftJoin('p.Reservation r WITH r.start_date>', date('Y-m-d')) But once this basic one is written correctly. Thanks
Zeljko
Oh are you using Doctrine 1.2?
rojoca
I am using Doctrine 1.2 . I will try that SIZE(p.reservations) but I can't find any documentation for SIZE command.
Zeljko
I tried SUM(p.nr_of_bookings) as num_bookings' solution, but it didn't give me correct results. When I print_r results, 'num_bookings' is much higher number that it should be. After that, I placed this: $q->groupBy('p.id,p.nr_of_bookings') ->addHaving('num_of_reservations<p.nr_of_bookings') ; For a moment, this looks like results are correct based on my Unit tests. Another question; it grouping by nr_of_bookings a good idea? Does this aggreagate function work on single property or will affect other properties somehow? Property and Reservations are one-2-many related. Thanks.
Zeljko
Interesting thing: instead of SUM(p.nr_of_bookings), I placed this: ROUND(p.nr_of_bookings) as num_bookings This would fullfill Mysql demand for aggreate function and yet, not make any calculations. Also; groupBy('p.id,p.nr_of_bookings') didn't work after all. Can you tell me if something is wrong using that ROUND() aggregate function?
Zeljko
@Zeljko - `ROUND()` isn't supported in DQL (according to the docs). I just realized that `SUM(p.nr_of_bookings) = nr_of_bookings * num_reservations` because you join on reservations and then group them by id. Try this: `SUM(p.nr_of_bookings) / COUNT(r.id) as num_bookings` and see if it gives you the correct results
rojoca
YES, it was exactly what happened. About ROUND() ; interesting thing is this actually works VERY nice. I have written many unit tests and no fails so far. But, I trust your judgement and will also try that other suggestion later. Thanks again...
Zeljko
@Zeljko - If `ROUND()` works - great! I just couldn't find it in the documentation which is why I made the other suggestion.
rojoca