首页 > 解决方案 > SQL查询,仅按一列分组

问题描述

我只想按项目对这个查询进行分组,因为同一个项目有两条记录,但我只想要一个。但是当我添加 group by 子句时,它会要求我添加其他列以及哪些分组不起作用。

*

DECLARE @Year varchar(75) = '2018'
DECLARE @von DateTime = '1.09.2018'
DECLARE @bis DateTime = '30.09.2018'
select new_projekt ,new_geschftsartname, new_mitarbeitername, new_stundensatz
from Filterednew_projektkondition ps
left join Filterednew_fakturierungsplan fp on ps.new_projekt = fp.new_hauptprojekt1
where ps.statecodename = 'Aktiv'
  and fp.new_startdatum >= @von +'00:00:00' 
  and fp.new_enddatum <= @bis +'23:59:59'
  --and new_projekt= Filterednew_projekt.new_
--group by new_projekt

*

查看 new_projekt 列。第 2 行和第 3 行有相同的项目,但我希望它只出现一次。由于其他列不同,这是不可能的。如果感兴趣,还有另一个coluim projectcondition id,对两者都是唯一的 结果

标签: sqlsql-serverssrs-2012

解决方案


你不能让数据库为你随意决定,做组的时候应该扔掉哪些记录。你必须准确和具体

例如,这里有一些关于一个人的数据:

Name, AddressZipCode
John Doe, 90210
John Doe, 12345

SELECT name, addresszipcode FROM person INNER JOIN address on address.personid = person.id

为这个人存储了两个地址,输出中重复了人员数据!

“我不要那个,我只想看到这家伙的一行字,连同他的地址”

哪个地址?

这就是你必须告诉数据库的

“嗯,显然是他现在的地址”

你如何表示一个地址是当前的?

“这是结束日期为空的那个”

SELECT name, addresszipcode FROM person INNER JOIN address on address.personid = person.id WHERE address.enddate = null

如果您仍然得到两个地址,则有两个地址记录为空 - 您的数据违反了您的业务数据建模原则(“一个人的地址历史记录最多应该有一个当前地址,用 null 表示结束日期") - 修复数据

“为什么我不能按名字分组?”

你可以,但如果你这样做了,你仍然必须告诉数据库如何积累它显示给你的非名字数据。你想要一个地址数据,它有 2 个要显示给你,你必须告诉它要丢弃哪个。你可以这样做:

SELECT name, MAX(addresszipcode) FROM person INNER JOIN address on address.personid = person.id GROUP BY name

“但我不想要最大邮政编码?这没有意义”

好的,使用 MIN、SUM、AVG,任何有意义的东西。如果这些都没有意义,则使用有意义的东西,例如具有最高结束日期的地址行,或作为未来结束日期的最低结束日期。如果您只希望显示一个地址,您必须决定如何将这些数据归结为一条记录 - 您必须编写数据库要遵循的规则,毫无疑问,您必须创建一个规则,所以让它成为一个规则描述你真正想要的


好的,所以您创建了一个规则 - 您只需要具有最小 new_stundenstatz 的行

DECLARE @Year varchar(75) = '2018'
DECLARE @von DateTime = '1.09.2018'
DECLARE @bis DateTime = '30.09.2018'
select new_projekt ,new_geschftsartname, new_mitarbeitername, new_stundensatz
from 

(SELECT *, ROW_NUMBER() OVER(PARTITON BY new_projekt ORDER BY new_stundensatz) rown FROM Filterednew_projektkondition) ps

left join 
Filterednew_fakturierungsplan fp on ps.new_projekt = fp.new_hauptprojekt1 
where ps.statecodename = 'Aktiv'
  and fp.new_startdatum >= @von +'00:00:00' 
  and fp.new_enddatum <= @bis +'23:59:59'
  and ps.rown = 1

在这里,我使用分析操作对 PS 表中的行进行编号。它们按升序编号new_stundensatz,从 1 开始。编号在更改时重新开始new_projekt,因此每个new_projekt编号都有 1 行。然后我们将其作为 where 的条件

(对将来应用这种技术很有帮助。如果是我们要添加行号的 FP 表,我们需要放入AND fp.rown= 1ON 子句,而不是 WHERE 子句,因为将它放在 where 会使LEFT 连接的行为类似于 INNER,隐藏没有任何 FP 匹配记录的行)


推荐阅读