SQL 查询,仅按一列分组

SQL query , group by only one column

我只想按项目对这个查询进行分组,因为同一个项目有两条记录,但我只想要一条。 但是当我添加 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,它对两者都是唯一的

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

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

Name, AddressZipCode
John Doe, 90210
John Doe, 12345

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

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

"I don't want that. I only want to see one line for this guy, together with his address"

哪个地址?

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

"Well, obviously his current address"

如何表示地址是最新的?

"It's the one with the null enddate"

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

如果你仍然得到两个地址,有两个地址记录是空的 - 你的数据违反了你的业务数据建模原则("a person's address history shall have at most one adddress that is current, denoted by a null end date") - 修复数据

"Why can't i just group by name?"

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

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

"But I don't want the max zipcode? That doesn't make sense"

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


好的,所以您创建了一个规则 - 您只需要具有最小 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 table 中的行编号。它们按 new_stundensatz 的升序编号,从 1 开始。当 new_projekt 更改时编号重新开始,因此每个 new_projekt 将有一个编号为 1 的行..然后我们将其制作where

的条件

(对将来应用此技术有帮助的旁注。如果它是我们要添加行号的 FP table,我们需要将 AND fp.rown= 1 放在 ON 子句中,不是 WHERE 子句,因为将它放在 where 中会使 LEFT 连接表现得像 INNER,隐藏没有任何 FP 匹配记录的行)