Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何在所有聚合行中检查某个值?_Sql_Oracle_Reporting_Analytics_Aggregate Functions - Fatal编程技术网

Sql 如何在所有聚合行中检查某个值?

Sql 如何在所有聚合行中检查某个值?,sql,oracle,reporting,analytics,aggregate-functions,Sql,Oracle,Reporting,Analytics,Aggregate Functions,假设我有三个表:user、group和xref,一个为它们提供多对多RI的表 我可能希望了解每个用户所属的组: select user.user_id, user.user_name, count(*) as group_count from user inner join xref on user.user_id = xref.user_id inner join group on group.group_id = xref.gr

假设我有三个表:
user
group
xref
,一个为它们提供多对多RI的表

我可能希望了解每个用户所属的组:

select
    user.user_id,
    user.user_name,
    count(*) as group_count
from
    user
        inner join xref on user.user_id = xref.user_id
        inner join group on group.group_id = xref.group_id
group by user.user_id, user.user_name
到目前为止一切都还好。但是,如果我想要一些额外的信息呢?我正在报告,我想知道每个用户是开发人员还是内容经理。现在,出现了一种反模式:

select
    user.user_id,
    user.user_name,
    count(*) as group_count,
    max( case group.group_name when 'Developers' then 'Y' else null end )
        as is_dev
    max( case group.group_name when 'Content Management' then 'Y' else null end )
        as is_cm
from
    user
        inner join xref on user.user_id = xref.user_id
        inner join group on group.group_id = xref.group_id
group by user.user_id, user.user_name
这是可行的,并产生了预期的结果,但感觉非常错误。我想问Oracle的是:

select
    user.user_id,
    user.user_name,
    count(*) as group_count,
    any(group.group_name, 'Developers', 'Y', null) as is_dev,
    any(group.group_name, 'Content Management', 'Y', null) as is_cm
from
    user
        inner join xref on user.user_id = xref.user_id
        inner join group on group.group_id = xref.group_id
group by user.user_id, user.user_name
“对于每个用户,请向我显示他们所在的组数。此外,对于每个用户的所有组名,请向我显示“开发人员”是否为其中一个值。”

我真正想问的是:

“对于每个用户,请向我显示他们所在的组数。此外,对于每个用户的所有组名,请向我显示此
case
表达式产生的最高值。”

这是一个反模式的原因是,我基本上依赖于这样一个事实,即当使用
max()进行计算时,
Y
恰好在
null
上方“冒泡”。如果有人想要复制或扩充这个查询,他们很容易忘记反模式,并意外地将返回值更改为不使用相同的非直观巧合的值

基本上,我希望我能写的问题是:

select
    user.user_id,
    user.user_name,
    count(*) as group_count,
    any(group.group_name, 'Developers', 'Y', null) as is_dev,
    any(group.group_name, 'Content Management', 'Y', null) as is_cm
from
    user
        inner join xref on user.user_id = xref.user_id
        inner join group on group.group_id = xref.group_id
group by user.user_id, user.user_name
我一直在筛选选择,似乎有一些潜力:

  • first\u value
    可以工作,但我不知道如何将相应的
    分区
    窗口限制到正确的行
  • 带有
    over
    子句的分析函数可能会工作,但我确实希望折叠我分组所依据的列,因此它似乎不是一个完美的匹配
  • 令人恼火的是,似乎有一个
    any
    函数被记录在案,但它只存在于一种神秘的方言中,称为Oracle OLAP DML,我认为我不能仅使用SQL在10g上访问它。但是,它似乎正是我想要的
我只有这些了。有什么想法吗


我知道有两个非常简单的想法,“在代码中实现”或“在PL/SQL中实现”,但这是欺骗。:-)

我会从MAX切换到SUM(用1而不是Y),所以你说的是“计算这个人所在的组的数量,其中组名是Developers”

然后,这种模式类似于“计算购买价值超过30美元的销售数量”

如果需要,您可以添加另一个表达式,表示“如果计数大于零,那么‘是’此人是开发人员”。非常明确,但可能没有必要

SELECT  user.user_id,
        user.user_name,
        COUNT(*) group_count,
        COUNT(DISTINCT DECODE(group_name, 'Developers', 'Y', NULL)) AS is_developer
        COUNT(DISTINCT DECODE(group_name, 'Content Management', 'Y', NULL)) AS is_content_manager
FROM    the_query
对于
ANY
,它是类似于
中的
的谓词,而不是函数:

SELECT  *
FROM    dual
WHERE   'baz' = ANY('foo', 'bar', 'baz')
我更喜欢,但是如果您想坚持使用布尔返回,您可以通过返回'N'而不是null,使排序更加明确

select
    user.user_id,
    user.user_name,
    count(*) as group_count,
    max( case group.group_name when 'Developers' then 'Y' else 'N' end )
        as is_dev
    max( case group.group_name when 'Content Management' then 'Y' else 'N' end )
        as is_cm
from
    user
        inner join xref on user.user_id = xref.user_id
        inner join group on group.group_id = xref.group_id
group by user.user_id, user.user_name

(+1表示写得很好的问题)

投了赞成票,因为
SUM()
似乎不是什么好办法。但是,我现在坚持接受任何答案。谢谢用户是否同时属于开发人员和内容管理人员?这就是你需要两个独立列的原因吗?与其在标题中添加[SQL],我只需要使用“SQL”标记。@现在到这里-是的,这就是原因。@Nick Pierpoint-当你在上面写问题时,它会根据标题为你提供一个潜在的类似问题列表。其他一些问题是在[SQL]前面加上的,我发现这是一种有用的方法,可以找到实际上相关的“类似”建议。所以,我复制了公约!:-)我不认为在标题中添加标签是一种惯例:感谢+1和答案。不幸的是,“N”成为了我在问题中提到的同一个问题的受害者,这就是你依赖的事实是“N”恰好排序高于“Y”。例如,如果您使用的不是“Y”和“N”,而是“Always”和“Never”,那么每个单元格都将是“Never”,因为
max
将始终拾取它。这是一个不直观的“明白了”,我相信这是一个真正的反模式的一部分。正如我所说,我更喜欢计数,但我认为你使用Y和N作为标志是非常安全的。