如何混合 COUNT() 和非 COUNT() 列而不丢失查询中的信息?

Posted

技术标签:

【中文标题】如何混合 COUNT() 和非 COUNT() 列而不丢失查询中的信息?【英文标题】:How can I mix COUNT() and non-COUNT() columns without losing information in the query? 【发布时间】:2009-01-13 16:26:21 【问题描述】:

我从一个查询开始:

SELECT strip.name as strip, character.name as character
  from strips, characters, appearances
 where strips.id = appearances.strip_id
   and characters.id = appearances.character.id
   and appearances.date in (...)

这给了我一些结果:

strip                 | character
'Calvin & Hobbes'     | 'Calvin'
'Calvin & Hobbes'     | 'Hobbes'
'Pearls Before Swine' | 'Pig'
'Pearls Before Swine' | 'Rat'
'Pearls Before Swine' | 'Hobbes'  # a guest appearance
'Pearls Before Swine' | 'Calvin'  # a guest appearance

然后我还想获得COUNT 在结果集中(在任何条带中)使用字符的次数。所以我尝试了:

SELECT count(character.id), strip.name as strip, character.name as character
  from strips, characters, appearances
 where strips.id = appearances.strip_id
   and characters.id = appearances.character.id
   and appearances.date in (...)

但这给了我

[ERROR 11:20:17] Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause

所以我尝试了:

SELECT count(character.id), strip.name as strip, character.name as character
  from strips, characters, appearances
 where strips.id = appearances.strip_id
   and characters.id = appearances.character.id
   and appearances.date in (...)
 group by character.id

这给了我

count | strip                 | character
4     | 'Calvin & Hobbes'     | 'Calvin'
4     | 'Calvin & Hobbes'     | 'Hobbes'
2     | 'Pearls Before Swine' | 'Pig'
2     | 'Pearls Before Swine' | 'Rat'

也就是说,我丢失了关于哪些字符出现在哪些条带中的所有额外信息。

我想要的是这个:

count | strip                 | character
4     | 'Calvin & Hobbes'     | 'Calvin'
4     | 'Calvin & Hobbes'     | 'Hobbes'
2     | 'Pearls Before Swine' | 'Pig'
2     | 'Pearls Before Swine' | 'Rat'
4     | 'Pearls Before Swine' | 'Calvin'
4     | 'Pearls Before Swine' | 'Hobbes'

但我似乎无法弄清楚。如果重要的话,我在 mysql 上。也许只需要两个查询。

【问题讨论】:

【参考方案1】:

mySQL 是否支持分析函数?喜欢:

SELECT foo.bar, baz.yoo, count(baz.yoo) over (partition by foo.bar) as yoo_count 
from foo, bar
where foo.baz_id = baz.id and baz.id in (...)

或者:

SELECT foo.bar, baz.yoo, v.yoo_count 
from foo, bar, 
( select foo.baz_id, count(*) as yoo_count
  from foo
  group by foo.baz_id
) as v
where foo.baz_id = baz.id and baz.id in (...)
and v.baz_id = foo.baz_id;

【讨论】:

MySQL 不做分区,后者给我错误信息“子查询返回超过 1 行。”【参考方案2】:

按 foo.bar 分组怎么样?

SELECT count(baz.id) as count, foo.bar, baz.yoo where foo.baz_id = baz.id and baz.id in (...) group by foo.bar

【讨论】:

【参考方案3】:

在 RDBMS 系统上,我会将计数查询选择到临时表中,然后将临时表重新加入主表。这将为您提供两全其美的体验。

不过,我不知道 mySQL 是否支持临时表。

【讨论】:

【参考方案4】:

如果 MySQL 支持分析/窗口函数,那么:

select bar, yoo,
    count(yoo) over (partition by yoo) c 
from t
/

否则您需要使用相关子查询:

select bar, yoo,
    (select count(yoo) from t t2 where t2.yoo=t.yoo) c 
from t
/

在 oracle 上,测试数据如下:

create table t(bar number, yoo varchar2(16));

insert into t(bar, yoo) values (1, 'hello');

insert into t(bar, yoo) values (2, 'goodbye');

insert into t(bar, yoo) values (3, 'goodbye');

insert into t(bar, yoo) values (4, 'goodbye');

insert into t(bar, yoo) values (2, 'calvin');

insert into t(bar, yoo) values (5, 'Hobbes');

insert into t(bar, yoo) values (6, 'Hobbes');

commit;

【讨论】:

【参考方案5】:

子选择:

SELECT foo.bar
    ,baz.yoo
    ,(SELECT COUNT(*) FROM baz AS baz2 WHERE baz2.yoo = baz.yoo etc.) AS yoo_count
FROM foo, baz
WHERE foo.baz_id = baz.id
    AND baz.id in (...)

您也可以将子选择嵌套并加入。

【讨论】:

不,这给了我每行返回的所有行的总数。【参考方案6】:

如果我要经常需要这样的计数字段,那么我会创建一个用户定义的函数来返回值并在普通选择中使用它。

【讨论】:

以上是关于如何混合 COUNT() 和非 COUNT() 列而不丢失查询中的信息?的主要内容,如果未能解决你的问题,请参考以下文章

sql 显示如何选择某些列内容的COUNT和SUM。第1行从Customers表中选择列,以及COUNT

创建具有记录类型列的表

如何按 2 列分组,但按 count() 降序排列

如何创建使用 groupby 的列属性?

Redshift:分析数据库中所有表中具有空值的所有列

excel2007学习VBA之笔记--计算混合料孔隙比