SQL查询,仅按一列分组

标签 sql sql-server ssrs-2012

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

最佳答案

你不能要求数据库为你任意决定,在进行分组时哪些记录应该被丢弃。您必须准确且具体

例如,以下是有关某人的一些数据:

Name, AddressZipCode
John Doe, 90210
John Doe, 12345

从人员 INNER JOIN 地址中选择姓名、地址邮政编码,地址为 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"

从人员 INNER JOIN 地址中选择姓名、地址邮政编码,地址为 address.personid = person.id,其中 address.enddate = null

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

"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 以及任何有意义的值。如果这些都没有意义,则使用有意义的东西,例如具有最高结束日期的地址行,或具有 future 结束日期的最低结束日期。如果您只想显示一个地址,您必须决定如何将该数据简化为一条记录 - 您必须编写数据库要遵循的规则,毫无疑问您必须创建一条规则 所以让它成为一条描述你真正想要什么的规则


好的,您创建了一条规则 - 您只需要具有最小 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= 1 放在 ON 中子句,而不是 WHERE 子句,因为将其放在 where 中会使 LEFT 连接表现得像 INNER,隐藏没有任何 FP 匹配记录的行)

关于SQL查询,仅按一列分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52850843/

相关文章:

sql - ClojureQL 与 clojure.contrib.sql 相比如何?

sql - 按时间戳分钟在 postgres 中查询

c# - 在C#中用参数动态替换SQL字符串

reporting-services - 查询查找已嵌入数据源的 ssrs 报告

sql - 如何在SQL Server数据库中添加自动增量主键?

mysql - 授予所有特权的逆

c# - 在 C# 中使用 SQL 表而不是字典引用

c# - 如何让 Entity Framework 生成 INSERT 语句以包含数据库生成的 IDENTITY 列?

reporting-services - SSRS参数和图像怎么了?

sql - CASE WHEN 中的 OR 关键字本身位于 WHERE 子句中