使用带有where子句的M​​ySQL group by子句

时间:2015-08-01 11:52:22

标签: mysql sql

我有两个表,一个存储产品信息,另一个存储产品评论。

我现在正试图获得两个日期之间为产品提交的评论数量,但出于某种原因,无论我提出的日期如何,我都会得到相同的结果。

这是我的疑问:

SELECT 
    productName,
    COUNT(*) as `count`,
    avg(rating) as `rating`
FROM `Reviews`
LEFT JOIN `Products` using(`productID`)
WHERE `date` BETWEEN '2015-07-20' AND '2015-07-30' 
GROUP BY 
    `productName` 
ORDER BY `count` DESC, `rating` DESC;

返回:

+------------+---------------------+
| productName| count|rating        |
+------------+------+--------------+
| productA   | 23   | 4.3333333    |
| productB   | 17   | 4.25         |
| productC   | 10   | 3.5          |
+------------+---------------------+

产品表:

+---------+-------------+
|productID | productName|
+---------+-------------+
|    1    | productA    |  
|    2    | productB    | 
|    3    | productC    |
+---------+-------------+ 

评论表

+---------+-----------+--------+---------------------+
|reviewID | productID | rating | date                |
+---------+-----------+--------+---------------------+
|    1    |      1    |   4.5  |  2015-07-27 17:47:01|
|    2    |      1    |   3.5  |  2015-07-27 18:54:22|
|    3    |      3    |   2    |  2015-07-28 13:28:37|
|    4    |      1    |   5    |  2015-07-28 18:33:14|
|    5    |      2    |   1.5  |  2015-07-29 11:58:17|
|    6    |      2    |   3.5  |  2015-07-30 15:04:25|
|    7    |      2    |   2.5  |  2015-07-30 18:11:11|
|    8    |      1    |   3    |  2015-07-30 18:26:23|
|    9    |      1    |   3    |  2015-07-30 21:35:05|
|    10   |      1    |   4.5  |  2015-07-31 14:25:47|
|    11   |      3    |   0.5  |  2015-07-31 14:47:48|
+---------+-----------+--------+---------------------+

当我把两个随机日期确定为肯定他们不在日期栏上时,我仍会得到相同的结果。即使我只想在某一天检索记录,我也会得到相同的结果。

3 个答案:

答案 0 :(得分:2)

您不应该使用左连接,因为这样做可以从一个表中检索所有数据。您应该使用的是:

set

答案 1 :(得分:1)

您在LEFT JOINreviews表之间使用了products。这将导致显示reviews的所有行,其中一些行将所有product列留空。

您应该使用INNER JOIN,因为这只会过滤想要的结果。

(最后我只能猜测,因为我甚至不知道哪一列属于哪个表......)

完整查询(非常类似于Angelo Giannis的解决方案):

select
     productName,
     count(*) as `count`,
     avg(rating) as `rating`
from
     products INNER JOIN reviews USING(productId)
where date between '2015-07-20' and '2015-07-30'
group by productName
order by count desc, rating desc;

这里有一个myAngelo's解决方案的小提琴(它们都有效)。

答案 2 :(得分:1)

如果给出您的样本数据,那么您正在寻找的结果是:

df.to_csv('filename', index=False)

这是在| productName | count | rating | |-------------|-------|--------| | productA | 5 | 4 | | productB | 3 | 3 | | productC | 1 | 2 | 2015-07-20之间的任何日期进行的评论的计数和平均值。

然后您的查询有两个问题。首先,您需要将联接更改为2015-07-30而不是inner join,但更重要的是,您需要更改日期条件,因为您目前不包括该范围中最后一个日期的评论,但午夜过后。

这是因为您的left join子句将日期时间值与日期值进行比较,因此比较最终为between,这明显排除了最后的某些日期。

修复方法是更改​​日期条件,以便结束一天后:

date between '2015-07-20 00:00:00' and '2015-07-30 00:00:00'

或将where date >= '2015-07-20' and date < '2015-07-31' 列投射到date值,这将删除时间部分:

date

Sample SQL Fiddle