sql - 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,对两者都是唯一的
解决方案
你不能让数据库为你随意决定,做组的时候应该扔掉哪些记录。你必须准确和具体
例如,这里有一些关于一个人的数据:
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= 1
ON 子句,而不是 WHERE 子句,因为将它放在 where 会使LEFT 连接的行为类似于 INNER,隐藏没有任何 FP 匹配记录的行)
推荐阅读
- gcloud - 如何通过 gcloud cli args 或环境变量将 secretEnv 指定给 cloudbuild.yaml
- bluetooth - 蓝牙 LE 传感器与笔记本电脑 BLE,信号强度的差异?
- windows - 如何从 Windows 内核模式驱动程序代码中获取当前工作目录?
- c++ - 将 ' :: ' 替换为 ' 。' 在 C++ 中产生歧义?
- stata - 基于二元选择设置每组内变量的值
- rust - Rust - 混合默认宏和个人默认实现
- javascript - 不明白如何在工具提示中显示提示
- android - 请问我将如何使用 Retrofit 参数化这个端点?
- android - 如何使用gson解析通过retrofit2从json数组中检索特定数据
- javascript - 如何停止在 HTML 中显示重复的 JSON 数据?