0

我有两个表 table1 和 table2。我想获得主题的年度分布。我为主题数据制作了第二张表。我创建了随机表 table1 和 table2。

tabel1

id | year
1  | 2001
2  | 2003
3  | 2001
4  | 2002
5  | 2001

我有第二张共享“id”的桌子

table2

id | topic | subtopic
1  | sport | volley 
1  | water | ok
1  | stock | apple
2  | stock | us 
2  | stock | pine
3  | world | uk
3  | water | salt
4  | water | sweet
4  | world | ep
5  | sport | volley
5  | stock | apple
5  | stock | pine

主题的热门类别是股票(3 = 1,2,5),水(3 = 1,3,4),运动(2 = 1,5),世界(2 = 2,4)

而且,假设我只想要前两个“主题”数据,所以我的输出数据将是

     stock | water
    ----------------
2001    2  |  2
2002    0  |  1
2003    1  |  0

到目前为止,我已经设法为个别主题做到了

SELECT table1.year AS YEAR, COUNT(DISTINCT table2.id ) AS lcount
FROM table1, table2
WHERE topic = 'stock'
AND table1.id = table2.id
GROUP BY YEAR

主题不仅限于4个,可以有n个不同的主题。因此,要找到 n 个不同的主题。我需要从他们那里挑选前 2 名。

4

2 回答 2

2

您可以使用带有 CASE 表达式的聚合函数来获取结果:

select t1.year,
  count(distinct case when topic = 'stock' then t2.id end) stock,
  count(distinct case when topic = 'water' then t2.id end) water,
  count(distinct case when topic = 'sport' then t2.id end) sport,
  count(distinct case when topic = 'world' then t2.id end) world
from table1 t1
left join table2 t2
  on t1.id = t2.id
group by t1.year;

请参阅SQL Fiddle with Demo

如果您将返回未知数量的值或未知主题,则必须使用动态 SQL 来获取结果:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'count(distinct CASE WHEN topic = ''',
      topic,
      ''' THEN t2.id END) AS `',
      topic, '`'
    )
  ) INTO @sql
FROM
(
  select count(distinct id) total, topic
  from table2 
  group by topic
  order by total desc
  limit 2
) d;

SET @sql 
  = CONCAT('SELECT t1.year, ', @sql, ' 
            from table1 t1
            left join table2 t2
              on t1.id = t2.id
            group by t1.year');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

请参阅带有演示的 SQL Fiddle

于 2013-07-01T19:48:41.947 回答
0

这是未经测试的,但应该可以解决问题:

SELECT a.`year`,
    COALESCE(b_stock.rec_count, 0) as `stock`,
    COALESCE(b_water.rec_count, 0) as `water`
FROM table1 a
LEFT JOIN (
    SELECT b2.`year`, COUNT(b.*) as rec_count
    FROM table2 b
    JOIN table1 b2 ON b2.id = b.id
    WHERE b.topic = 'stock'
    GROUP BY b2.year
) b_stock ON b_stock.`year` = a.`year` 
LEFT JOIN (
    SELECT b2.`year`, COUNT(b.*) as rec_count
    FROM table2 b
    JOIN table1 b2 ON b2.id = b.id
    WHERE b.topic = 'water'
    GROUP BY b2.year
) b_water ON b_water.`year` = a.`year`
GROUP BY a.`year`
ORDER BY a.`year`
于 2013-07-01T19:43:40.690 回答