SQL GROUP BY возвращает пустой набор - PullRequest
0 голосов
/ 20 февраля 2012

У меня аренда стола:

rentalId    int(11)              
Customer_customerId     int(11)          
Vehicle_registrationNumber  varchar(20)              
startDate   datetime             
endDate     datetime         
pickUpLocation  int(11)                  
returnLocation  int(11)                      
booking_time    timestamp                
timePickedUp    timestamp            
timeReturned    timestamp   

и таблица оплаты:

paymentId   int(11)                      
Rental_rentalId     int(11)      
amountDue   decimal(10,2)                
amountPaid  decimal(10,2)            
paymentDate     timestamp

Я запускаю две группы по функциям, первая подсчитывает количество резервирований и суммирует платежи по дням, эта функция работает только так, как ожидается, когда параметр pickUpLocation` опущен, в противном случае она возвращает неправильные значения. :

SELECT COUNT(rentalId) AS number_of_rentals, MONTH(booking_time) AS month,
`YEAR(booking_time) AS year, 
CONCAT(DAY(booking_time), '-', MONTH(booking_time), '-',`
YEAR(booking_time) ) AS date, SUM(amountDue) AS total_value, SUM(amountPaid) AS 
total_paid, `pickUpLocation`

FROM (`rental`)
JOIN `payment` ON `payment`.`Rental_rentalId` = `rental`.`rentalId`

GROUP BY DAY(booking_time)

HAVING `month` = 2
AND `year` = 2012
AND `pickUpLocation` = 1
ORDER BY `booking_time` desc

LIMIT 31  

Ожидается, что вторая функция будет суммировать резервирования и платежи (как причитающиеся, так и полученные) за весь месяц для определенного местоположения:

 SELECT COUNT(rentalId) AS number_of_rentals, MONTH(booking_time) AS month, 
 YEAR(booking_time) AS year, SUM(amountDue) AS total_value, 
 SUM(amountPaid) AS total_paid,
 `pickUpLocation`

  FROM (`rental`)
  JOIN `payment` ON `payment`.`Rental_rentalId` = `rental`.`rentalId`

  GROUP BY MONTH(booking_time)

  HAVING `month` = 2
  AND `year` = 2012
  AND `pickUpLocation` = 1
  ORDER BY `booking_time` desc  

Он работает для некоторых местоположений и не работает для других (возвращает правильный набор, когда есть много резервирований, но когда их всего несколько, он возвращает пустой набор). Я использую MySQL. Любая помощь с благодарностью.

Ответы [ 2 ]

3 голосов
/ 20 февраля 2012

Вы выполняете внутреннее соединение между rental и payment, что означает, что вы всегда будете получать только аренду, которая была оплачена. Если вы хотите найти аренду без информации об оплате в своем результате, вам нужно использовать LEFT JOIN вместо (внутреннего) JOIN.

Обратите внимание, что это может привести к NULL в вашем результате, если нет платежей для учета, поэтому вам, возможно, придется настроить вывод вашего запроса, используя одну из функций потока управления .

Редактировать: Вы также GROUP перед вашими условиями, которые будут GROUP все строки за месяц в одну строку. Поскольку год и PickupLocation могут различаться, вы получите случайные значения (из доступных) в этих двух полях. HAVING будет фильтровать эти случайные поля, оставляя вам возможно пустой набор результатов. WHERE, с другой стороны, будет видеть каждую строку перед GROUP ing и делать правильные вещи (tm) в зависимости от строки к строке, поэтому вместо этого следует поставить условия.

(Такое же изменение, вероятно, следует внести в ваш первый рабочий запрос)

Демо здесь .

1 голос
/ 20 февраля 2012

Вам может потребоваться перевести некоторые условия из условия HAVING в WHERE:

WHERE YEAR(booking_time) = 2012
  AND MONTH(booking_time) = 2
  AND `pickUpLocation` = 1

GROUP BY DAY(booking_time)

LIMIT 31

В течение определенного месяца вам даже не нужны GROUP BY:

WHERE YEAR(booking_time) = 2012
  AND MONTH(booking_time) = 2
  AND `pickUpLocation` = 1

Вышеуказанное условие не очень хорошо с точки зрения производительности:

WHERE YEAR(booking_time) = 2012
  AND MONTH(booking_time) = 2

Вы должны изменить его на:

WHERE booking_time >= '2012-02-01'
  AND booking_time < '2012-03-01'

, чтобы запрос мог использовать индекс для booking_time (если у вас есть или вы добавляете один в будущем), и поэтому он не вызывает функции YEAR() и MONTH() для каждой строки таблицы.

...