1

背景情報

システム

OS:

bash$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 6.0.5 (squeeze)
Release:        6.0.5
Codename:       squeeze

MySQL:

bash$ mysql --version
mysql  Ver 14.14 Distrib 5.1.63, for debian-linux-gnu (x86_64) using readline 6.1

データベース

エンジン:MyISAM

テーブル:post_votes

mysql> describe post_votes;
+-----------+---------------------+------+-----+---------+----------------+
| Field     | Type                | Null | Key | Default | Extra          |
+-----------+---------------------+------+-----+---------+----------------+
| id        | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| post_uuid | binary(16)          | YES  |     | NULL    |                |
| user_uuid | binary(16)          | YES  |     | NULL    |                |
| vote      | tinyint(4)          | YES  |     | 0       |                |
+-----------+---------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

表:投稿

mysql> describe posts;
+-------------+---------------------+------+-----+----------------------+----------------+
| Field       | Type                | Null | Key | Default              | Extra          |
+-------------+---------------------+------+-----+----------------------+----------------+
| id          | bigint(20) unsigned | NO   | PRI | NULL                 | auto_increment |
| post_uuid   | binary(16)          | YES  | UNI | NULL                 |                |
| owner_uuid  | binary(16)          | YES  |     | NULL                 |                |
| created     | int(10) unsigned    | YES  |     | NULL                 |                |
| edited      | int(10) unsigned    | YES  |     | NULL                 |                |
| title       | varchar(50)         | YES  |     | NULL                 |                |
| description | varchar(150)        | YES  |     | NULL                 |                |
| link        | varchar(100)        | YES  |     | NULL                 |                |
| properties  | varchar(20)         | YES  |     | 00000000000000000000 |                |
+-------------+---------------------+------+-----+----------------------+----------------+
9 rows in set (0.00 sec)

問題

賛成/反対の比率に応じて投稿を選択したい。賛成票と反対票を数えるクエリを思いついたのですが、実際の投稿に結合できないようです。

動作中の(不完全な)クエリ

(
    SELECT COUNT(*), post_uuid, 'upvotes' AS 'mode'
    FROM post_votes a
    WHERE a.vote = 1
    GROUP BY post_uuid
)
UNION
(
    SELECT COUNT(*), post_uuid, 'downvotes' AS 'mode'
    FROM post_votes a
    WHERE a.vote = -1
    GROUP BY post_uuid
)

壊れたクエリ

(
    (
        SELECT COUNT(*), post_uuid, 'upvotes' AS 'mode'
        FROM post_votes a
        WHERE a.vote = 1
        GROUP BY post_uuid
    )
    UNION
    (
        SELECT COUNT(*), post_uuid, 'downvotes' AS 'mode'
        FROM post_votes a
        WHERE a.vote = -1
        GROUP BY post_uuid
    )
)
a
LEFT JOIN posts b ON a.post_uuid = b.post_uuid

私は何が間違っているのですか?私が受け取るエラーメッセージは次のとおりです。

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'UNION
(
SELECT COUNT(*), post_uuid, 'downvotes' AS 'mode'
4

1 に答える 1

2

UNIONペアは事実上派生テーブルであり、に参加するには句に含まれている必要がありFROMますJOIN。これは句に含まれているため、その列FROMが必要です。そうでない場合、クエリには句がまったくありません。MySQLの構文は寛大ですが、欠落している句を許可するほど寛大ではありません。SELECTSELECTSELECT

/* SELECT the cols produced by the UNION */
SELECT 
   a.`num`, 
   a.`post_uuid`,
   a.`mode`,
  /* And other columns from `posts` if needed */
   b.`something`,
   b.`something_else`,
   b.`some_other_thing`
/* UNIONs are a derived table, belonging in FROM */
FROM (
    (
        SELECT COUNT(*) as num, post_uuid, 'upvotes' AS 'mode'
        FROM post_votes a
        WHERE a.vote = 1
        GROUP BY post_uuid
    )
    UNION
    (
        SELECT COUNT(*) num, post_uuid, 'downvotes' AS 'mode'
        FROM post_votes a
        WHERE a.vote = 1
        GROUP BY post_uuid
    )
) a
LEFT JOIN posts b ON a.post_uuid = b.post_uuid

これを見ると、集約パターンUNIONを使用することで、を単純化できると思います。SUM(CASE)

SELECT 
  b.post_uuid,
  SUM(CASE WHEN a.vote = 1 THEN 1 ELSE 0 END) AS upvotes,
  /* Assume -1 for downvotes? */
  SUM(CASE WHEN a.vote = -1 THEN 1 ELSE 0 END) AS downvotes
FROM
  posts b
  LEFT JOIN post_votes a ON a.post_uuid = b.post_uuid
GROUP BY b.post_uuid
于 2012-11-26T00:03:56.833 に答える