我有两个主要的 SELECT 语句在单独运行时返回所需的结果,但在组合时不返回所需的结果。
查询 1
这工作正常,返回预期的结果。
SELECT feed_mode_id FROM user WHERE id=2;
+--------------+
| feed_mode_id |
+--------------+
| 1 |
+--------------+
查询 2
这也很好。有时结果是空的,有时不是。
SELECT
answer.id AS answer_id
FROM
answer
WHERE
answer.question_id = (
SELECT
question.id
FROM
question
ORDER BY
datetime_added_utc DESC
LIMIT 1
)
AND answer.user_id = 2;
Empty set (0.00 sec)
查询 1 和 2 合并
当将它们组合成如下所示的两个子 SELECT 语句时,
feed_mode_id
是 NULL
,但 x.feed_mode_id
的结果应该如查询 1 所示。这是我对这些组合语句如何工作的缺乏了解。SELECT
x.feed_mode_id,
IF (COUNT(y.answer_id) < 1, 0, 1) AS answered_question
FROM
(SELECT
user.feed_mode_id
FROM
user
WHERE
user.id = 2) AS x,
(SELECT
answer.id AS answer_id
FROM
answer
WHERE
answer.question_id = (
SELECT
question.id
FROM
question
ORDER BY
datetime_added_utc DESC
LIMIT 1
)
AND answer.user_id = 2) AS y
+--------------+-------------------+
| feed_mode_id | answered_question |
+--------------+-------------------+
| NULL | 0 |
+--------------+-------------------+
为什么是
feed_mode_id
生产 NULL
而不是 1
?我也对完全重写查询的不同方法持开放态度。期望的结果是:+--------------+-------------------+
| feed_mode_id | answered_question |
+--------------+-------------------+
| 1 | 0 |
+--------------+-------------------+
这在某种程度上与查询 2 的结果在这种情况下为空的事实有关。对于查询 2 返回值(非空)的情况,组合查询将按需要工作。
最佳答案
您有一个介于 x
之间的笛卡尔积和 y
.只要这些行源中的每一个只返回一行,查询就会返回一行。
我建议您放弃用于连接操作的老式逗号语法,并使用 JOIN
而是关键字。
此外,除了返回“最近添加”问题的子查询之外,还不清楚为什么需要内联 View 和子查询。
我不完全清楚您实际尝试返回的结果集,但看起来您正在确定特定用户(由“user”表的“id”列唯一标识)是否提供了“答案” “最近添加的问题”。
如果这是您尝试返回的结果,我相信此查询将返回该结果:
SELECT u.feed_mode_id
, IF( COUNT(a.id) < 1, 0, 1) AS answered_question
FROM ( SELECT q.id
FROM question q
ORDER BY q.datetime_added_utc DESC, q.id DESC
LIMIT 1
) r
JOIN user u
ON u.id = 2
LEFT
JOIN answer a
ON a.user_id = u.id
AND a.question_id = r.id
GROUP BY u.id
注意:内联 View 别名为
r
返回 id
的“最近添加”question
. (在原始查询中,如果两个或多个问题具有相同的 datetime_added_utc
,则不确定将返回哪一行。此查询通过在 ORDER BY 子句中添加另一个表达式来确定它。(可以拉出内联 View 查询并单独运行,以验证它是否返回了预期的结果。)从
r
返回的行(如果有的话)然后连接到从“用户”表u
中检索到的一行。 .我们在这里假设 id
“用户”表中的列是唯一标识符,并且可能是“用户”表的主键。如果我们有一个“最近添加”的问题(即
r
中的一行),并且“用户”中的一行与 u.id=2
匹配ON
中的谓词子句,那么到目前为止,我们保证查询将返回单行。接下来,我们执行“外连接”操作,从“答案”表中找到匹配的行。
ON
中的谓词子句将返回的行限制为仅具有 user_id
的行匹配 id
来自 u
(在本例中,等同于指定 a.user_id=2
,并具有与“最近添加”问题 question_id
的 id
匹配的 r
。LEFT
关键字将此标识为“外部连接”;如果“answer”表中没有匹配的行,则查询仍将返回 r
中的行和 u
. (如果这是一个内连接,也就是说,如果我们删除了 LEFT
关键字,那么如果“answer”表中没有匹配的行,那么查询将不会返回一行。)我们添加一个
GROUP BY u.id
子句,以防我们从 answer
获得多个匹配行; GROUP BY
导致具有相同 u.id 值的所有行折叠成一行。COUNT()
聚合计算 id
的非空出现次数从“答案”表中。如果没有找到匹配的行,则 a.id 将为 NULL,因此 COUNT(a.id) 将返回 0。如果我们正在寻找多个用户,如果我们为 user.id 指定多个值来匹配,那么同样的查询也可以工作,例如
ON u.id IN (2,3,5,7)
或者,如果我们完全不使用该谓词,那么我们会为每个用户返回一行。这个查询仍然有效。
但在这两种情况下,我们还想添加
u.id AS user_id
到查询的 SELECT 列表,这样我们就可以知道哪一行是针对哪个用户的。如果我们想返回最近添加的两个问题,我们可以更改
r
中的 LIMIT 子句,然后添加 r.id
到GROUP BY
条款。同样,我们可能还想返回 r.id AS question_id
在 SELECT 列表中,所以我们知道哪一行是针对哪个问题的。
关于php - 组合 SELECT 语句的 MySQL 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25778135/