我怎样才能在加入的路上加上条件?

时间:2016-03-27 10:54:06

标签: php mysql performance if-statement

我有这个表结构:

// QandA
+----+---------------------+----------------------------------------+------+---------+
| Id |         title       |                   content              | type | related |
+----+---------------------+----------------------------------------+------+---------+
| 1  | title of question 1 | content of question1                   | 0    | 1       |
| 2  |                     | content of first answer for question1  | 1    | 1       |
| 3  | title of question 2 | content of question2                   | 0    | 3       |
| 4  |                     | content of second answer for question1 | 1    | 1       |
| 5  |                     | content of first answer for question2  | 1    | 3       |
+----+---------------------+----------------------------------------+------+---------+

type列:0表示这是一个问题而1表示这是一个答案。

related列:对于问题,此列包含其自身的ID,对于答案,此列包含其问题的ID。

还有其他依赖表:

// Votes
+----+---------+---------+-------+
| id | post_id | user_id | value |
+----+---------+---------+-------+
| 1  | 1       | 1234    | 1     |
| 2  | 2       | 1234    | -1    |
| 3  | 1       | 4321    | 1     |
+----+---------+---------+-------+

// Favorites
+----+---------+---------+
| id | post_id | user_id |
+----+---------+---------+
| 1  | 1       | 1234    |
| 2  | 1       | 4321    |
+----+---------+---------+

好的,这是我的问题中的主要注意事项: Favorites表只属于问题(不是答案)。答案永远不会是最喜欢的(只是问题可以)

这也是我的疑问:

SELECT 
   p.title, p.content,
   vv.value AS cuvv -- cuvv is stand for current_user_vote_value,
   CASE WHEN ff.id IS NOT NULL THEN '2' ELSE '3' END AS cuf -- current_user_favorite
   (SELECT SUM(v.value) FROM Votes v WHERE p.id = v.post_id) AS total_votes,
   (SELECT COUNT(1) FROM Favorites f WHERE p.id = f.post_id) AS total_favorites,
FROM QandA p
   LEFT JOIN Votes vv ON p.id = vv.post_id AND vv.user_id = :user_id_1
   LEFT JOIN favorites ff ON p.id = ff.post_id AND f.user_id = :user_id_2
WHERE p.related = :id

注意:对于cuf2表示当前用户已将此问题标记为收藏,3表示他没有(在换句话说,3表示此问题不是当前用户的最爱

好的,让我传递一些参数来查询并执行它:(作为示例)

$user_id = 1234;
$id      = 1;

$sth->bindValue(":user_id_1", $user_id, PDO::PARAM_INT);
$sth->bindValue(":user_id_2", $user_id, PDO::PARAM_INT);
$sth->bindValue(":id", $id, PDO::PARAM_INT);
$sth->execute();

这是输出:

-- cuvv is stand for current_user_vote_value
-- cuf  is stand for current_user_favorite

+--------------+----------------------+------+-----+-------------+-----------------+
|    title     |      content         | cuvv | cuf | total_votes | total_favorites |
+--------------+----------------------+------+-----+-------------+-----------------+
| title of ... | content of que ...   | 1    | 2   | 2           | 2               |
|              | content of fir ...   | -1   | 3   | -1          | 0               |
|              | content of sec ...   | NULL | 3   | 0           | 0               |
+--------------+----------------------+------+-----+-------------+-----------------+

好的,我的问题是什么?

这两列cuftotal_favorites只属于问题(type = 0)。但我的查询不知道。我的意思是我的查询计算所有行的总收藏数,我想知道,如何判断:仅针对问题计算cuftotal_favorites,而不是问题和答案?

换句话说,我需要设置一个IF条件来检查p.type = 0是否然后执行这两行:

(SELECT COUNT(1) FROM Favorites f WHERE p.id = f.post_id) AS total_favorites,

LEFT JOIN favorites ff ON p.id = ff.post_id AND f.user_id = :user_id_2

否则不会执行这两行,因为如果p.type = 1,则这两行是浪费而无用的。

如何实现该条件并改进该查询?

2 个答案:

答案 0 :(得分:1)

您可能想要尝试的一种方法是在子查询中仅查询收藏夹和投票表一次,并一次计算用户和所有值。

SELECT 
   q.title, q.content, 
   IFNULL(vv.user_val, 0) cuvv, IFNULL(vv.all_val, 0)  total_votes,
   IFNULL(ff.user_fav, 0) cuf,  IFNULL(ff.all_fav, 0)  total_favorites
FROM QandA q
LEFT JOIN (
  SELECT post_id, 
    SUM(value) all_val, SUM(CASE WHEN user_id=1234 THEN value END) user_val
  FROM votes GROUP BY post_id
) vv 
  ON vv.post_id = q.id
LEFT JOIN (
  SELECT post_id, 
    COUNT(1) all_fav, COUNT(CASE WHEN user_id=1234 THEN 1 END) user_fav
  FROM favorites GROUP BY post_id
) ff 
  ON q.type=0 AND ff.post_id = q.id
WHERE q.related = 1;

An SQLfiddle to test with

答案 1 :(得分:1)

试试这个:

printf("%d", atoi(argv[1]));