如何显示所有非聚合字段值

Posted

技术标签:

【中文标题】如何显示所有非聚合字段值【英文标题】:How to show all non-aggregate field values 【发布时间】:2018-09-18 14:46:27 【问题描述】:

我可能忽略了一些简单的东西,但我没有看到它。 假设我有一个参与者和分数表

[Name]   [Score]
Tom      12
Tom      14
Tom      20
Dick     14
Dick     17
Harry    23

我想向所有参加过一次以上的人展示他们的所有分数。这意味着在此示例中,我想显示除最后一条以外的所有记录。 第一部分很简单 - 只需按名称分组并添加 having count([Score])>1。但是如何也显示所有分数呢?

我尝试不分组并添加count([Score]) over (partition by [Name]),但这不是一个有效的过滤表达式。你不能这样做(count([Score]) over (partition by [Name]))>1

所以最后我选择了

SELECT * from [Table]
where [Name] in (
     SELECT [Name] from [Table]
     GROUP by [Name]
     HAVING count([Score])>1
)

这行得通,但我想知道是否有更好的方法。 (真正的查询更长,涉及更多的连接表,所有这些都必须在内部选择中重复,所以这感觉......很脏。违反了 DRY 原则。) 这是我能做的最好的吗?还是有更好的办法?

【问题讨论】:

【参考方案1】:

是的,还有其他方法是使用exists 而不是in

select * 
from table t
where exists (
    select 1 from table 
    where name = t.name
    group by name
    having count(1) > 1
)

【讨论】:

【参考方案2】:

你做得很好。计算子查询中的重复名称,然后使用它们的结果过滤原始表是无法逃脱的。您可以使用INEXISTS,尽管它们略有不同(使用IN 时,如果至少有一个结果是NULL,那么它将永远不会匹配!)。我宁愿改用EXIST

SELECT 
    T1.* 
from 
    [Table] T1
where
    EXISTS (
        SELECT
            'the name appears at least twice with not null score'
        FROM
            [table] T2
        WHERE
            T1.name = T2.name -- NULL names won't match here!
        GROUP BY
            T2.name
        HAVING
            COUNT(score) > 1)

【讨论】:

好的...感谢有关 NULL 结果的警告。但是,如果我将查询更改为使用 EXISTS,则执行时间是 IN 的两倍。 (正如我所说,实际查询更复杂,涉及更多表。)有解决方案吗?我的主表没有可为空的字段,所有的连接都是内连接,所以不会有任何 NULL 结果,我宁愿使用生产中最快的版本。 您可以尝试在 CTE 或子查询中进行窗口计数,然后过滤结果,这可能比再次重复大查询以按名称分组要快。

以上是关于如何显示所有非聚合字段值的主要内容,如果未能解决你的问题,请参考以下文章

MS SQL 中的非聚合字段

使用 mongoDB 中的聚合删除集合中所有文档的特定字段

分组和求和,使用非聚合标准来确定字段选择

C # 如何连接到sql 数据库 要详细的代码,为啥显示字段初始值无法引用非静态字段?!

如何在猫鼬聚合中使用字段值? (节点)

SQL Server中的聚合函数都有哪些?