我有两个主要的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返回值(非空)的情况,组合查询将按预期工作。
答案 0 :(得分:1)
您在x
和y
之间有笛卡尔积。只要每个行源只返回一行,查询就会返回一行。
我建议您放弃连接操作的旧式逗号语法,而是使用JOIN
关键字。
此外,还不清楚为什么你需要内联视图和子查询,除了返回&#34;最近添加&#34;的子查询。问题
我并不完全清楚你实际上想要返回什么结果集,但看起来你正在确定一个特定的用户(由&#34; id&#34;列唯一标识&#34; ; user&#34; table),提供了一个&#34;答案&#34;到了最近添加的问题&#34;。
如果这是您尝试返回的结果,我相信此查询将返回该结果:
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
注意:内嵌视图别名为r
会返回&#34; {34}最近添加的&#34;} id
。 (在原始查询中,如果两个或多个问题具有相同的question
,则不确定将返回哪一行。此查询通过向ORDER BY子句添加另一个表达式来确定它。(内联查看查询可以被拉出并单独运行,以验证它是否返回了预期的结果。)
然后将从datetime_added_utc
返回的行(如果有的话)连接到从&#34;用户&#34;中检索到的行。表格1}}。我们在此假设&#34;用户&#34;中的r
列。 table是唯一标识符,可能是&#34; user&#34;的主键。表
如果我们有一个&#34;最近添加的&#34;问题(即来自u
的一行),并且来自&#34;用户&#34;与id
子句中的r
谓词匹配,到目前为止,我们保证查询将返回单行。
接下来,我们执行&#34;外部联接&#34;操作,从&#34;回答&#34;找到匹配的行表。 u.id=2
子句中的谓词将返回的行限制为仅ON
与ON
user_id
匹配的行(在此示例中,相当于指定id
},和的u
与&#34的a.user_id=2
匹配;最近添加的&#34;问题question_id
。
id
关键字将此标识为&#34;外部联接&#34 ;;如果&#34;答案&#34;没有匹配的行表,然后查询仍将返回r
和LEFT
的行。 (如果这是一个内部联接,也就是说,如果我们删除了r
关键字,那么如果&#34; answer&#34;表中没有匹配的行,那么查询将不会返回一行。 )
我们添加u
子句,以防我们从LEFT
获得多个匹配行; GROUP BY u.id
会将具有相同u.id值的所有行折叠为一行。
answer
汇总从&#34;答案&#34;计算GROUP BY
的非空出现次数。表。如果找不到匹配的行,则a.id将为NULL,因此COUNT(a.id)将返回0.
如果我们要查找多用户,如果我们为user.id指定了多个值来匹配,那么同样的查询也会有效。
COUNT()
或者如果我们完全离开该谓词,那么我们为每个用户排了一行。此查询仍然有效。
但是在其中任何一种情况下,我们还想将id
添加到查询的SELECT列表中,这样我们就知道哪一行是针对哪个用户的。
如果我们想要返回两个最近添加的问题,我们可以更改 ON u.id IN (2,3,5,7)
中的LIMIT子句,然后将u.id AS user_id
添加到r
条款。同样,我们可能还想在SELECT列表中返回r.id
,因此我们知道哪一行是针对哪个问题。
答案 1 :(得分:0)
完全查询
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 IN (
SELECT
question.id
FROM
question
ORDER BY
datetime_added_utc DESC
LIMIT 1
)
AND answer.user_id = 2) AS y
answer.question_id =回答.question_id IN
答案 2 :(得分:0)
我不想回答我自己的问题,但我找到了一个有效的解决方案。我已将IF语句移动到子SELECT而不是主SELECT。我不知道为什么这样做,以前的尝试没有,但它现在产生了预期的结果。
SELECT
x.feed_mode_id,
y.question_answered
FROM
(SELECT
user.feed_mode_id
FROM
user
WHERE
user.id = 2) AS x,
(SELECT
IF (COUNT(answer.id < 1), 1, 0) AS question_answered
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 | question_answered |
+--------------+-------------------+
| 1 | 0 |
+--------------+-------------------+