【问题标题】:Complex (ish) SQL join and count query复杂(ish)SQL 连接和计数查询
【发布时间】:2009-07-29 10:33:03
【问题描述】:

我正在尝试使用 php 和 sql 创建一个简单的轮询函数。 我有三张桌子:

问题

其中仅包含所问的每个问题

question_id |问题文本 | created_at

答案

其中包含每个问题的每个答案

question_id | answer_id | answer_text

已回答的问题

哪些记录谁为每个选项投票

question_id | answer_id |用户ip

我正在尝试编写一个查询,该查询将返回一个问题(最新的)以及该问题的所有可能答案,最后计算每个问题的每个答案的计数。我知道我将不得不使用 GROUP BY 子句和可能的 LEFT OUTER JOIN,但确切的语法让我无法理解。

任何建议将不胜感激。谢谢。

【问题讨论】:

  • 为什么要在第三个表中保留question_id? question_id 由 answer_id 定义。
  • @Quassnoi:除非他的主键是复合的(question_id,answer_id)。
  • @Hosam Aly:你认为一个答案可以应用于多个问题?
  • @Quassnoi:不,但他可能已将主键配置为复合,分别计算每个问题的答案 ID。 (例如 Q1 有答案 A1、A2 和 A3;Q2 有答案 A1 和 A2。)

标签: php sql join count


【解决方案1】:

这与本文http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/中的逻辑非常相似。

基本上,您需要一个子查询来选择您感兴趣的单个记录/问题,以及一个外部查询来选择与您感兴趣的记录相关的信息

(我可以发布另一个 SQL 语句以添加到已经发布的漂亮集合中,但我想我会尝试阐明其他发布的查询是如何工作的)

【讨论】:

    【解决方案2】:

    此查询应该适用于大多数 DBMS:

    select q.question_id, question_text, a.answer_id, a.answer_text, count(user_ip)
      from questions q
     inner join answers a on (q.question_id = a.question_id)
      left join answered_questions aq on (a.question_id = aq.question_id
                                          and a.answer_id = aq.answer_id)
     where created_at = (select max(created_at)
                           from questions
                         )
     group by q.question_id, a.answer_id, q.question_text, a.answer_text
    

    【讨论】:

    • 您的查询不考虑同时创建两个问题的情况 - 您应该将子查询替换为 WHERE q.question_id = (SELECT TOP 1 question_id FROM QUESTIONS ORDER BY created_at DESC)
    • 有两个问题具有相同的created_at 时间对于 OP 来说将是一个问题,因为他应该有一个明确的标准来识别他所要求的最近的问题。使用TOP 并不能解决问题,因为 1) 它会返回任意记录,并且 2) 并非所有数据库都支持它(例如 MySQL 和 PostgreSQL 使用 LIMIT 代替)。
    • 谢谢,这似乎是迄今为止最接近我需要的。但是,它为每个答案返回两行。例如:你最喜欢的颜色是什么?蓝橙红蓝橙红
    • @Dan:这绝不应该发生,除非您的数据中有不正确的地方。我们同时按question_id 和answer_id 进行分组,因此表answers 中的单行不能出现两次。您的数据是否可能存在重复?
    【解决方案3】:

    假设你是 MySQL:

    SELECT  q.* ,
            (
            SELECT  COUNT(*)
            FROM    answered_questions aq
            WHERE   aq.answer_id = a.answer_id
                    AND aq.question_id = q.question_id
            ) AS votes
    FROM    (
            SELECT  *
            FROM    question
            ORDER BY
                    created_at DESC
            LIMIT 1
            ) q
    LEFT OUTER JOIN
            answers a
    ON      a.question_id = q.question_id
    

    【讨论】:

      【解决方案4】:
      SELECT
          questions.question_id,
          questions.question_text,
          answers.answer_id,
          answers.answer_text,
          COUNT(answered_questions.user_ip)
      FROM
          questions,answers,
          answered_questions
      WHERE
          questions.question_id=answers.question_id
          AND
          questions.question_id=
              (SELECT
                  question_id
                  FROM questions
                  ORDER BY questions.created_at
                  LIMIT 1
              )
          AND
          answered_questions.question_id=questions.question_id
      GROUP BY
          questions.question_id
      

      应该可以工作(虽然我还没有测试过)。

      【讨论】:

      • 这样好多了。但此查询将选择最近的问题(而不是 OP 要求的最近的问题)。
      猜你喜欢
      • 2010-11-02
      • 2012-11-29
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多