SQL GROUP BY返回空集

时间:2012-02-19 23:03:00

标签: mysql sql group-by grouping

我有桌子出租:

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 个答案:

答案 0 :(得分:3)

您正在rentalpayment之间进行内部联接,这意味着您只能获得已付款的租金。如果您想在结果中找到没有付款信息的租借,则需要使用LEFT JOIN而不是仅使用(内部)JOIN

请注意,如果没有要付款的付款,结果可能会导致结果中出现NULL,因此您可能需要使用control flow functions之一来调整查询的输出。

编辑:您也是GROUP在您的条件之前,GROUP将{1}}一行中的所有行合并为一行。由于年份和PickupLocation可能会有所不同,您将获得这两个字段中的随机值(可用的值)。然后HAVING将对这些随机字段进行过滤,为您留下可能为空的结果集。另一方面,WHERE将在GROUP之前看到每一行,并在行到行的基础上做正确的事情(tm),因此条件应放在那里。

(可能应该对您的第一个工作查询进行同样的更改)

演示here

答案 1 :(得分:1)

您可能需要将某些条件从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()函数调用桌子的一排。