1

ユーザー (「投票者」) がさまざまなオブジェクト (場所、Web サイト、回答など、「投票者」) を 1 つから 5 つの星 (「スコア」) で評価する仮説を表すこの表があるとします。この質問のより一般的なバージョンでは、代わりに 1 から N の foo に対して何をすべきかを尋ねます。

mysql> SHOW CREATE TABLE scores;
CREATE TABLE `scores` (
    `voter_id` BIGINT NOT NULL DEFAULT '0',
    `votee_id` BIGINT NOT NULL DEFAULT '0',
    `score` tinyint NOT NULL,
    PRIMARY KEY (`voter_id`,`votee_id`),
    KEY `votee_index` (`votee_id`)
);

オブジェクトに与えられた 1、2、3、4、および 5 つの星の投票の数を表す列を持つ、各投票オブジェクトの .csv ファイルを作成したいと考えています。

output.csv:
votee_id, count_ones, count_twos, count_threes, count_fours, count_fives
1, 3, 7, 5, 3, 2
...

このクエリを使用して、このテーブルを裏付ける生データを取得できることはわかっています。

SELECT votee_id, score, COUNT(score)
FROM scores
GROUP BY votee_id, score;

これは、私が考えたいcsv形式のデータを私に与えません:

  1. 特定のオブジェクトで表示されないスコアの 0 は表示されません。

  2. オブジェクトの 5 つのスコアすべてを単一の行/行に結合するわけではありません (つまり、データを非正規化/ヒストグラム化します)。

mysql だけを使用して出力を作成したい。

しばらくハッキングした後、次のクエリが機能します。しかし、それはかなり非効率的であり、よりエレガントなものを見つけたり作成したりすることはできません:

SELECT votee_id, GROUP_CONCAT(COALESCE(score_count, '0') ORDER BY AllUserCrossScore.score ASC)
FROM
    (SELECT votee_id, score FROM
        (SELECT 1 AS score UNION ALL
         SELECT 2 AS score UNION ALL
         SELECT 3 AS score UNION ALL
         SELECT 4 AS score UNION ALL
         SELECT 5 AS score) ScoresEnum

         JOIN

         (SELECT DISTINCT votee_id FROM scores) DistinctIds
    ) AllUserCrossScore

    LEFT JOIN

    (SELECT votee_id, score, COUNT(score) as score_count
     FROM scores
     GROUP BY votee_id, score
    ) ScoreCounts

    USING (votee_id, score)
GROUP BY votee_id;

特に、スコアをまとめるために GROUP_CONCAT を ',' と共に使用しているため、これは特にハッキリと感じます。次に、他のすべてのフィールドを ',' で結合するように mysql を他の場所で操作すると、.csv の正しい書式が得られます (操作は示されていません)。

このような場合、どうすればもっとうまくいくでしょうか?

4

2 に答える 2

1

私はあなたがこのようなものを探していると思います:

SELECT
  votee_id
  SUM(CASE WHEN score = 1 THEN 1 ELSE 0 END) as count_ones
  SUM(CASE WHEN score = 2 THEN 1 ELSE 0 END) as count_twos
  SUM(CASE WHEN score = 3 THEN 1 ELSE 0 END) as count_threes
  SUM(CASE WHEN score = 4 THEN 1 ELSE 0 END) as count_fours
  SUM(CASE WHEN score = 5 THEN 1 ELSE 0 END) as count_fives
FROM scores
GROUP BY votee_id
于 2012-12-17T21:23:19.270 に答える
0

元の SQL をラップしてください。

SELECT
  votee_id AS votee_id,
  SUM(IF(score=1,count_score,0)) AS count_ones,
  SUM(IF(score=2,count_score,0)) AS count_twos,
  SUM(IF(score=3,count_score,0)) AS count_threes,
  SUM(IF(score=4,count_score,0)) AS count_fours,
  SUM(IF(score=5,count_score,0)) AS count_fives
FROM (
  SELECT votee_id, score, COUNT(score) as count_score
  FROM scores
  GROUP BY votee_id, score
) AS baseview
GROUP BY votee_id;
于 2012-12-17T21:24:13.777 に答える