SQL连接和三个表的计数

时间:2014-07-29 06:32:00

标签: mysql join multiple-tables

我有三个表格,其中包含以下相关列

  • 产品:ProductID
  • 评论:ReviewID,ProductID,UserID
  • 用户:UserId,StateID

并非所有产品都有评论,但所有评论都有产品和用户。

我已经编写了一个查询,该查询返回所有产品详细信息以及正在运行的审核计数。现在我想限制审核次数,因此它只包含用户状态为1的评论(例如,未删除/禁止)。这就是我所拥有的,但它并不是很有效

SELECT product.*, count(r.ProductId) as reviewCount, u.state
FROM Product p
LEFT OUTER JOIN Review r ON p.id = r.ProductId
LEFT OUTER JOIN Users u ON u.userId = r.userId AND u.state IN (1)
GROUP BY p.id

计数仍然包括用户状态为2的评论。任何人都可以发现我做错了吗?我在SQL上显然不是那个闪存。

执行计数的工作SQL是这个

SELECT product.*, count(r.ProductId) as reviewCount
FROM Product p
LEFT OUTER JOIN Review r ON p.id = r.ProductId
GROUP BY p.id

这里是一些样本表的DDL。它创建了三辆汽车(car1,car2,car3),为car1添加了三个评论,为car2添加了一个评论,但对car2进行评论的其中一个用户的状态为1(即忽略):

create database products;
use products;
CREATE TABLE Product (ProductID int(10)  AUTO_INCREMENT, name varchar(20),     primary key(ProductID));
CREATE TABLE Review (ReviewID int(10) AUTO_INCREMENT, ProductID int(10), UserID int(10), score int(10), primary key(ReviewID));
CREATE TABLE User (UserId int(10) AUTO_INCREMENT, StateID int(10), name varchar(20), primary key(UserId));
insert into product values (1, 'car1'), (2, 'car2'), (3, 'car3');
insert into review values (1, 1, 1, 10), (2, 1, 2, 5), (3, 1, 3, 7), (4, 2, 1, 5);
insert into user values (1, 2, 'bob'), (2, 2, 'fred'), (3, 1, 'inactive');
// NB: three reviews of car 1, one by an inactive user. One review of car two by active user.

所以结果应该是:

ProductID    name    reviewCount
        1    car1              2
        2    car2              1
        3    car3              0

3 个答案:

答案 0 :(得分:1)

下面的查询不起作用,因为您将联接留给用户,这意味着如果相关用户处于状态2,您仍然会看到他们的评论,只是来自用户的相关字段的空值(可能您看到u.state是对于用户处于状态2)

的行,为null
SELECT product.*, count(r.ProductId) as reviewCount, u.state
FROM Product p
LEFT OUTER JOIN Review r ON p.id = r.ProductId
LEFT OUTER JOIN Users u ON u.userId = r.userId AND u.state IN (1)
GROUP BY p.id

您可以更改查询以删除u.state上的谓词,并将查询中的COUNT替换为CASE语句的SUM,CASE评估为1表示有效用户评论,0表示其他用户评估如下:

SELECT product.*, SUM(CASE WHEN u.state NOT IN (1) THEN 1 ELSE 0 END) AS reviewCount
FROM Product p
LEFT OUTER JOIN Review r ON p.id = r.ProductId
LEFT JOIN Users u ON u.userId = r.userId
GROUP BY p.id

我已经尝试过您之前提供的测试用例,在无效用户的car3评论中添加了该测试用例,并且工作正常。

答案 1 :(得分:0)

尝试简单

SELECT _p.*, count(_r.ProductID) as reviewCount, _u.stat
FROM Product _p 
INNER JOIN Review _r ON _r.ProductID = _p.ProductID
INNER JOIN User  _u ON _u.UserID = _r.UserID AND _u.StateID = 1;  
GROUP BY _p.ProductID

答案 2 :(得分:0)

你想要评论评论。因此,请计算ReviewId,而不是ProductId。而u.state条款中的where不是。SELECT p.*, count(r.ReviewId) as reviewCount FROM Product p LEFT OUTER JOIN Review r ON p.id = r.ProductId LEFT OUTER JOIN Users u ON u.userId = r.userId WHERE u.state = 1 GROUP BY p.id; 。试试这个:

SELECT ProductId, ProductName, count(ReviewId) as reviewCount
FROM Product p, Review r, User u
WHERE p.ProductId = r.ProductId AND r.UserId = u.UserId AND u.state = 1
GROUP BY p.ProductID;

修改

如果您尝试这样简单而繁重的请求会怎样? :

{{1}}