【问题标题】: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 原则。)
这是我能做的最好的吗?还是有更好的办法?

【问题讨论】:

    标签: tsql group-by aggregate-functions


    【解决方案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 或子查询中进行窗口计数,然后过滤结果,这可能比再次重复大查询以按名称分组要快。
      猜你喜欢
      • 1970-01-01
      • 2012-09-28
      • 2021-02-27
      • 1970-01-01
      • 2020-05-14
      • 2012-04-19
      • 2021-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多