MySQL SELECT结合3个SELECT INTO 1

时间:2010-05-26 12:04:23

标签: mysql

考虑以下MySQL数据库中的表:

entries:
    creator_id INT
    entry TEXT
    is_expired BOOL
other:
    creator_id INT
    entry TEXT

userdata:
    creator_id INT
    name VARCHAR
    etc...

entriesother中,1个创建者可以有多个条目。 userdata表仅供我阅读(放在其他数据库中)。

我想要获得以下SELECT结果:

+------------+---------+---------+-------+
| creator_id | entries | expired | other |
+------------+---------+---------+-------+
|      10951 |      59 |      55 |    39 | 
|      70887 |      41 |      34 |   108 | 
|      88309 |      38 |      20 |   102 | 
|      94732 |       0 |       0 |    86 |

...其中entries等于SELECT COUNT(entry) FROM entries GROUP BY creator_idexpired等于SELECT COUNT(entry) FROM entries WHERE is_expired = 0 GROUP BY creator_idother等于SELECT COUNT(entry) FROM other GROUP BY creator_id

我需要这个结构,因为在执行此SELECT之后,我需要在“userdata”表中查找用户数据,我计划使用INNER JOIN并选择所需的列。

我通过在列中选择“NULL”解决了这个问题,该列不适用于给定的SELECT:

SELECT
    creator_id,
    COUNT(any_entry) as entries,
    COUNT(expired_entry) as expired,
    COUNT(other_entry) as other
FROM (
    SELECT
        creator_id,
        entry AS any_entry,
        NULL AS expired_entry,
        NULL AS other_enry
    FROM entries
    UNION
    SELECT
        creator_id,
        NULL AS any_entry,
        entry AS expired_entry,
        NULL AS other_enry
    FROM entries
    WHERE is_expired = 1
    UNION
    SELECT
        creator_id,
        NULL AS any_entry,
        NULL AS expired_entry,
        entry AS other_enry
    FROM other
) AS tTemp
GROUP BY creator_id
ORDER BY
    entries DESC,
    expired DESC,
    other DESC
;

我遗漏了INNER JOIN并故意从userdata表中选择了其他列(我的问题是将3个SELECT组合成1个)。

  • 我的想法有效吗?我试图使用正确的“构造”吗?
  • 在不创建“空”列的情况下,这些SELECT是否可行? (某种加入)
  • 我应该“在DB之外”执行此操作:制作3个SELECT,在其中进行一些命令(比如python lists / dicts)然后为userdata执行额外的SELECT?

similar question的解决方案不会返回entriesexpired0的行。

感谢您的时间。

3 个答案:

答案 0 :(得分:1)

这应该有效(假设所有creator_id出现在userdata表中。

SELECT userdata.creator_id, COALESCE(entries_count_,0) AS entries_count, COALESCE(expired_count_,0) AS expired_count, COALESCE(other_count_,0) AS other_count
FROM userdata
  LEFT OUTER JOIN
  (SELECT creator_id, COUNT(entry) AS entries_count_
   FROM entries
   GROUP BY creator_id) AS entries_q
    ON userdata.creator_id=entries_q.creator_id
  LEFT OUTER JOIN
  (SELECT creator_id, COUNT(entry) AS expired_count_
   FROM entries
   WHERE is_expired=0
   GROUP BY creator_id) AS expired_q
    ON userdata.creator_id=expired_q.creator_id
  LEFT OUTER JOIN
  (SELECT creator_id, COUNT(entry) AS other_count_
   FROM other
   GROUP BY creator_id) AS other_q
    ON userdata.creator_id=other_q.creator_id;

答案 1 :(得分:0)

基本上,你所做的事情对我来说是正确的。

我会通过

重写如下
SELECT  entries.creator_id
        , any_entry
        , expired_entry
        , other_entry
FROM    (
          SELECT creator_id, COUNT(entry) AS any_entry,
          FROM entries
          GROUP BY creator_id
        ) entries
        LEFT OUTER JOIN (
          SELECT creator_id, COUNT(entry) AS expired_entry,
          FROM entries
          WHERE is_expired = 1
          GROUP BY creator_id        
        ) expired ON expired.creator_id = entries.creator_id
        LEFT OUTER JOIN (
          SELECT creator_id, COUNT(entry) AS other_entry
          FROM other
          GROUP BY creator_id
        ) other ON other.creator_id = entries.creator_id

答案 2 :(得分:0)

怎么样

SELECT creator_id,
   (SELECT COUNT(*)
        FROM entries e
        WHERE e.creator_id = main.creator_id AND
              e.is_expired = 0) AS entries,
   (SELECT COUNT(*)
        FROM entries e
        WHERE e.creator_id = main.creator_id AND
              e.is_expired = 1) as expired,
   (SELECT COUNT(*)
        FROM other
        WHERE other.creator_id = main.creator_id) AS other,
 FROM entries main
 GROUP BY main.creator_id;