加入条件表,依靠条件

时间:2014-10-28 22:11:51

标签: sql

SELECT *, null AS score,
       '0' AS SortOrder
    FROM products
    WHERE datelive = -1
    AND hidden = 0
UNION
SELECT e.*, (SUM(r.a)/(COUNT(*)*1.0)+
       SUM(r.b)/(COUNT(*)*1.0)+
       SUM(r.c)/(COUNT(*)*1.0)+
       SUM(r.d)/(COUNT(*)*1.0))/4 AS score,
       '1' AS SortOrder
    FROM products e
    LEFT JOIN reviews r
        ON r.productID = e.productID
        WHERE e.hidden = 0
        AND e.datelive != -1
    GROUP BY e.productID
    HAVING COUNT(*) >= 5
UNION
SELECT e.*, (SUM(r.a)/(COUNT(*)*1.0)+
       SUM(r.b)/(COUNT(*)*1.0)+
       SUM(r.c)/(COUNT(*)*1.0)+
       SUM(r.d)/(COUNT(*)*1.0))/4 AS score,
       '2' AS SortOrder
    FROM products e
    LEFT JOIN reviews r
        ON r.productID = e.productID
        WHERE e.hidden = 0
        AND e.datelive != -1
    GROUP BY e.productID
    HAVING COUNT(*) < 5
    ORDER BY SortOrder ASC, score DESC

这将创建一个用于在页面上显示产品的SQL对象。第一个请求会抓取datelive = -1类型的项目,第二个类型为datelive != -1r.count(*) >= 5,第三个类型为datelive != -1r.count(*) < 5。评论表的结构类似于以下内容:

 reviewID | productID | a | b | c | d | approved
-------------------------------------------------
    1           1       5   4   5   5      1
    2           5       3   2   5   5      0
    3           2       5   5   4   3      1
   ...         ...     ... ... ... ...    ...

我正在努力使r.count(*)仅关注approved = 1类型的行,因为根据未经批准的评论统计数据并不理想。如何加入这些表格,使得分数和行数的总和仅取决于approved = 1

我已尝试在AND r.approved = 1条件中添加WHERE加入条件,但它没有按照我的意愿行事。它会对它进行适当的排序,但之后它不再包含零评论的项目。

3 个答案:

答案 0 :(得分:2)

你好像差不多了。

在你的问题中,你谈到了将AND r.approved = 1添加到连接标准,但是通过它的声音,你实际上是将它添加到WHERE子句中。

如果您正确地将其添加到如下所示的连接条件,那么它应该可以正常工作:

SELECT *, null AS score,
       '0' AS SortOrder
    FROM products
    WHERE datelive = -1
    AND hidden = 0
UNION
SELECT e.*, (SUM(r.a)/(COUNT(*)*1.0)+
       SUM(r.b)/(COUNT(*)*1.0)+
       SUM(r.c)/(COUNT(*)*1.0)+
       SUM(r.d)/(COUNT(*)*1.0))/4 AS score,
       '1' AS SortOrder
    FROM products e
    LEFT JOIN reviews r ON r.productID = e.productID
    WHERE e.hidden = 0
    AND e.datelive != -1
    GROUP BY e.productID
    HAVING COUNT(*) >= 5
UNION
SELECT e.*, (SUM(r.a)/(COUNT(*)*1.0)+
       SUM(r.b)/(COUNT(*)*1.0)+
       SUM(r.c)/(COUNT(*)*1.0)+
       SUM(r.d)/(COUNT(*)*1.0))/4 AS score,
       '2' AS SortOrder
    FROM products e
    LEFT JOIN reviews r ON r.productID = e.productID AND r.approved = 1
    WHERE e.hidden = 0
    AND e.datelive != -1
    GROUP BY e.productID
    HAVING COUNT(*) < 5
    ORDER BY SortOrder ASC, score DESC

SQL Fiddle here

再次注意我是如何在AND r.approved = 1之后直接放置LEFT JOIN reviews r ON r.productID = e.productID,这为加入添加了额外的条件。

正如我在评论中提到的,WHERE子句将在连接完成后过滤组合记录集中的行。在某些情况下,RDBMS可以对其进行优化并将其置于连接标准中,但仅限于那些对结果集没有影响的地方。

答案 1 :(得分:1)

计算非零和并将其与结果相结合可以解决它;

fiddle

SELECT a.productID,
       NULL AS score,
       '0' AS SortOrder
FROM products a
WHERE datelive = -1
  AND hidden = 0
UNION
SELECT e.productID,
       (min(x.a)/(min(x.cnt)*1.0)+ min(x.b)/(min(x.cnt)*1.0)+ min(x.c)/(min(x.cnt)*1.0)+ min(x.d)/(min(x.cnt)*1.0))/4 AS score,
       '1' AS SortOrder
FROM products e
JOIN reviews r ON r.productID = e.productID
LEFT JOIN
  (SELECT ee.productID,
          sum(rr.a) AS a,
          sum(rr.b) AS b,
          sum(rr.c) AS c,
          sum(rr.d) AS d,
          count(*) AS cnt
   FROM products ee
   LEFT JOIN reviews rr ON ee.productID = rr.productID
   GROUP BY ee.productID) x ON e.productID = x.productID
WHERE e.hidden = 0
  AND e.datelive != -1
GROUP BY e.productID HAVING COUNT(*) >= 5
UNION
SELECT e.productID,
       (min(x.a)/(min(x.cnt)*1.0)+ min(x.b)/(min(x.cnt)*1.0)+ min(x.c)/(min(x.cnt)*1.0)+ min(x.d)/(min(x.cnt)*1.0))/4 AS score,
       '2' AS SortOrder
FROM products e
LEFT JOIN reviews r ON r.productID = e.productID
LEFT JOIN
  (SELECT ee.productID,
          sum(rr.a) AS a,
          sum(rr.b) AS b,
          sum(rr.c) AS c,
          sum(rr.d) AS d,
          count(*) AS cnt
   FROM products ee
   LEFT JOIN reviews rr ON ee.productID = rr.productID
   GROUP BY ee.productID) x ON e.productID = x.productID
WHERE e.hidden = 0
  AND e.datelive != -1
GROUP BY e.productID HAVING COUNT(*) < 5
ORDER BY SortOrder ASC,
         score DESC

答案 2 :(得分:-1)

您可以创建一个临时表,其中只包含approved = 1的行,然后加入临时表而不是reviews

create table tt_reviews like reviews;
insert into tt_reviews
select * from reviews
where approved = 1;
alter table tt_reviews add index(productID);

然后在上述查询中将reviews替换为tt_reviews