1

私が意味したのは:

次のテーブルを想像してください。

Table article_status:             Table users:

userid  | article | status        id | name
--------+---------+-------        ---+------
 1      | 1       | 1              1 | Peter
 1      | 2       | 2              2 | Bob
 2      | 3       | 1
 2      | 4       | 1
 2      | 5       | 2
 2      | 6       | 2
 2      | 7       | 3

私が取得したいのは、ユーザーのステータス番号でグループ化されたすべてのアイテムの数です。可能なステータス値の数は既知です (4)。

の結果の例users.id = 2:

userid | name | s1_count | s2_count | s3_count | s4_count |
-------+------+----------+----------+----------+----------+
 2     | Bob  | 2        | 2        | 1        | 0        |

私が試したこと:

SELECT 
  u.id AS userid
, u.name
, COUNT(s1.status) AS s1_count
, COUNT(s2.status) AS s2_count
, COUNT(s3.status) AS s3_count
, COUNT(s4.status) AS s4_count
FROM users AS u
INNER JOIN article_status AS s1 ON s1.userid = u.id AND s1.status = 1 
INNER JOIN article_status AS s2 ON s2.userid = u.id AND s2.status = 2 
INNER JOIN article_status AS s3 ON s3.userid = u.id AND s3.status = 3 
INNER JOIN article_status AS s4 ON s4.userid = u.id AND s4.status = 4 
WHERE u.id = :uid
LIMIT 1

しかし、これは機能せず (なぜ?)、非常に最適ではないように見えます。何か案は?

4

3 に答える 3

2

これは、データのピボットとして知られています... これを行う 1 つの方法は、CASEステートメントを使用することです。

SELECT 
  u.id
, u.name
, COUNT(CASE WHEN a_s.status = 1 THEN 1 END) AS s1_count
, COUNT(CASE WHEN a_s.status = 2 THEN 1 END) AS s2_count
, COUNT(CASE WHEN a_s.status = 3 THEN 1 END) AS s3_count
, COUNT(CASE WHEN a_s.status = 4 THEN 1 END) AS s4_count
FROM users AS u
INNER JOIN article_status AS a_s ON a_s.userid = u.id 
WHERE u.id = :uid
GROUP BY u.id, u.name
LIMIT 1
于 2013-01-02T19:38:50.143 に答える
1

で集計関数を使用してCASE、結果を取得できます。

SELECT 
  u.id,
  u.name,
  sum(CASE WHEN a.status = 1 THEN 1 else 0 END) s1_count,
  sum(CASE WHEN a.status = 2 THEN 1 else 0 END) s2_count,
  sum(CASE WHEN a.status = 3 THEN 1 else 0 END) s3_count,
  sum(CASE WHEN a.status = 4 THEN 1 else 0 END) s4_count
FROM users u
INNER JOIN article_status a 
  ON u.id = a.userid
GROUP BY u.id, u.name

SQL FiddlewithDemoを参照してください

または、多くのサブクエリを使用してデータを返すことができます。

select u.id,
  u.name,
  coalesce(s1_count, 0) s1_count,
  coalesce(s2_count, 0) s2_count,
  coalesce(s3_count, 0) s3_count,
  coalesce(s4_count, 0) s4_count
from users u
left join
(
  select count(*) s1_count, userid
  from article_status
  where status = 1
  group by userid
) s1
  on u.id = s1.userid
left join
(
  select count(*) s2_count, userid
  from article_status
  where status = 2
  group by userid
) s2
  on u.id = s2.userid
left join
(
  select count(*) s3_count, userid
  from article_status
  where status = 3
  group by userid
) s3
  on u.id = s3.userid
left join
(
  select count(*) s4_count, userid
  from article_status
  where status = 4
  group by userid
) s4
  on u.id = s4.userid

SQL FiddlewithDemoを参照してください

于 2013-01-02T19:55:03.830 に答える
0

COUNT(s1.status) のようなことをする代わりに、次のことを試してください

COUNT(DISTINCT(CONCAT(s1.article, '-', s1.status)))

ステータスと記事に明確に依存するため、これは私の理論にすぎません。それが機能するかどうか教えてください!

于 2013-01-02T19:36:29.703 に答える