【问题标题】:How can I mix COUNT() and non-COUNT() columns without losing information in the query?如何混合 COUNT() 和非 COUNT() 列而不丢失查询中的信息?
【发布时间】: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 上。也许只需要两个查询。

【问题讨论】:

    标签: sql


    【解决方案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】:

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

          【讨论】:

            猜你喜欢
            • 2013-12-15
            • 2010-12-17
            • 2019-05-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-05-16
            • 2016-02-02
            相关资源
            最近更新 更多