php - 组合 SELECT 语句的 MySQL 问题

标签 php mysql sql

我有两个主要的 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_idNULL ,但 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_idid 匹配的 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.idGROUP BY条款。同样,我们可能还想返回 r.id AS question_id在 SELECT 列表中,所以我们知道哪一行是针对哪个问题的。

关于php - 组合 SELECT 语句的 MySQL 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25778135/

相关文章:

mysql - 如何根据公用表从 2 个表中获取值

sql - Jython 使用 FDMApi 从 SQL 获取值

c++ - 为什么 sqlite3pp 样本会这样?

php - pChart,如何设置轴名称或轴标签之间的边距?

php - 关于mysql和php查询的问题

php - 如何在没有 Laravel 的情况下使用 Eloquent ORM?

mysql - 具有最大日期实例的 SQL 查询

javascript - 未捕获的类型错误 : Cannot read property 'val' of null jquery

mysql - 如果 mySQL 字段为空,则插入值

php - Yii:尝试使用带条件的 'uniqe' 规则时出错