【问题标题】:SQL Counting the number of occurence based on a subjectSQL根据主题统计出现次数
【发布时间】:2014-01-17 15:38:48
【问题描述】:

我很难说出我想要达到的目标。我有一个看起来像这样的表:

user char
---------
a | x
a | y
a | z
b | x
b | x
b | y
c | y
c | y
c | z

如何编写一个返回以下结果的查询?

user x y z
-------
a |1|1|1|
b |2|1|0|
c |0|2|1|

数字表示原始表中字符的出现次数

编辑: 字符值是未知的,因此解决方案不能仅限于这些值。抱歉没有早点提。我正在使用 Oracle DB,但计划使用 JPQL 来构建查询。

【问题讨论】:

  • 你用的是什么数据库? sql服务器? mysql?
  • 这是用于什么数据库平台的?
  • 可能的char 值是否仅限于xyz,或者它们可以是任何字符?
  • 很抱歉没有早点提到这个,char 值是未知的,因此它可以是任何字符。在 Vland 和 OldProgrammer,我正在使用 oracle DB,并将使用 JPQL 来构建查询
  • 不使用 XML,不确定您是否可以使用一组未知值进行 PIVOT(假设您正在寻找仅 SQL 的解决方案)

标签: sql oracle pivot jpql


【解决方案1】:
select user,
    sum(case when char='x' then 1 else 0 end) as x,
    sum(case when char='y' then 1 else 0 end) as y,
    sum(case when char='z' then 1 else 0 end) as z
from thetable
group by user

或者,如果您不介意垂直堆叠,此解决方案将为您提供一个即使对未知字符集也有效的解决方案:

select user, char, count(*) as count
from thetable
group by user, char

这会给你:

user   char   count
a      x      1
a      y      1
a      z      1
b      x      2

如果您想水平串出一组未知的值(如在您的演示输出中),您将需要进入动态查询... SQL 标准并非旨在生成具有未知数字的输出列...希望这有帮助!

【讨论】:

  • 如果他有 250 个可能的 char 值怎么办?
  • 那应该在问题中提到。
  • 很抱歉没有早点提及,char 值是未知的,因此它可以是任何字符。
  • 您确定需要将结果横向排列吗?因为它很容易垂直堆叠,即使是未知值。
  • 对不起,我无法通过垂直堆叠来想象你的意思。你介意给我一个例子来说明它的样子吗?如果不太牵强,我可能可以在 Java 中对数据进行后处理。
【解决方案2】:

另一个选项,使用T-SQL PIVOT (SQL SERVER 2005+)

select *
from userchar as t
pivot
(
    count([char]) for [char] in ([x],[y],[z]) 
) as p

结果:

user        x           y           z
----------- ----------- ----------- -----------
a           1           1           1
b           2           1           0
c           0           2           1

(3 row(s) affected)

编辑 ORACLE

您可以使用ORACLE 构建一个类似的 PIVOT 表。

棘手的部分是您需要在IN ([x],[y],[z],...) 语句中使用正确的列名。在代码中构造 SQL 查询,获取 (SELECT DISTINCT [char] from table) 并将其附加到您的基本查询中应该不会太难。

Pivoting rows into columns dynamically in Oracle

【讨论】:

    【解决方案3】:

    如果您不知道 PIVOT 的确切值,您将需要执行一些程序性操作或使用动态 sql(在匿名块中),或者使用 XML(在 11g 中)。

    如果你想要 XML 方法,它会是这样的:

    with x as (
      select 'a' as usr, 'x' as val from dual
      union all
      select 'a' as usr, 'y' as val from dual
      union all
      select 'b' as usr, 'x' as val from dual
      union all
      select 'b' as usr, 'x' as val from dual
      union all
      select 'c' as usr, 'z' as val from dual
    )
    select * from x
    pivot XML (count(val) as val_cnt for val in (ANY))
    ;
    

    输出:

    USR VAL_XML
    a   <PivotSet><item><column name = "VAL">x</column><column name = "VAL_CNT">1</column></item><item><column name = "VAL">y</column><column name = "VAL_CNT">1</column></item></PivotSet>
    b   <PivotSet><item><column name = "VAL">x</column><column name = "VAL_CNT">2</column></item></PivotSet>
    c   <PivotSet><item><column name = "VAL">z</column><column name = "VAL_CNT">1</column></item></PivotSet>
    

    希望有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-28
      • 1970-01-01
      • 1970-01-01
      • 2023-01-18
      相关资源
      最近更新 更多