如何混合 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() 列而不丢失查询中的信息?的主要内容,如果未能解决你的问题,请参考以下文章