如何显示所有非聚合字段值
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】:你做得很好。计算子查询中的重复名称,然后使用它们的结果过滤原始表是无法逃脱的。您可以使用IN
或EXISTS
,尽管它们略有不同(使用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 或子查询中进行窗口计数,然后过滤结果,这可能比再次重复大查询以按名称分组要快。以上是关于如何显示所有非聚合字段值的主要内容,如果未能解决你的问题,请参考以下文章