Sql 聚合不在分组依据中的列

Sql 聚合不在分组依据中的列,sql,sql-server-2008-r2,Sql,Sql Server 2008 R2,在T-SQL Server 2008 R2中,如果相关,那么编写以下查询的最干净方法是什么 select dfd.ListName as ProvName, COUNT(distinct pv.PatientProfileId) from PatientVisit pv join DoctorFacility dfd on pv.DoctorId = dfd.DoctorFacilityId group by pv.DoctorId 我可以想出几种不同的方法。事

在T-SQL Server 2008 R2中,如果相关,那么编写以下查询的最干净方法是什么

select dfd.ListName as ProvName, COUNT(distinct pv.PatientProfileId)
    from PatientVisit pv
        join DoctorFacility dfd on pv.DoctorId = dfd.DoctorFacilityId
    group by pv.DoctorId
我可以想出几种不同的方法。事实上,我可能只需要按dfd.ListName分组,但我只是有点偏执,担心会雇佣两个约翰·史密斯我知道另一个选择是

select dfd.ListName as ProvName, DistPatCount 
    from (
        select pv.DoctorId, COUNT(distinct pv.PatientProfileId) as DistPatCount
            from PatientVisit pv
            group by pv.DoctorId
        ) pvc 
        join DoctorFacility dfd on pvc.DoctorId = dfd.DoctorFacilityId

但“丑屁股”是我能想到的最有礼貌的形容方式此外,我想有人会知道我遗漏了什么…

如果SQL再聪明一点,你可以做以下事情,因为你知道一个医生只能有一个设施

select pv.DoctorId, dfd.ListName as ProvName, COUNT(distinct pv.PatientProfileId)
    from PatientVisit pv
        join DoctorFacility dfd on pv.DoctorId = dfd.DoctorFacilityId
    group by pv.DoctorId
不幸的是,SQL中的单值规则太严格,它阻止您这样做。单值规则是,select列表中的任何列都必须位于GROUP BY子句中,或者位于聚合函数中,而不管它在上述情况下实际上并不含糊

因此,我们可以编写以下代码以符合SQL,即使在逻辑上不需要将ListName放入聚合函数中:

select pv.DoctorId, MAX(dfd.ListName) as ProvName, COUNT(distinct pv.PatientProfileId)
    from PatientVisit pv
        join DoctorFacility dfd on pv.DoctorId = dfd.DoctorFacilityId
    group by pv.DoctorId

我假设pv.DoctorId是引用dfd.DoctorFacilityId的外键,而不是相反。

也许处理它最干净的方法是创建患者计数视图。我很难相信这是唯一有帮助的地方

或者,您可以定义一个CTE,它基本上是一个包含以下信息的内联视图:

WITH Patient_Count (SELECT doctorId, COUNT(DISTINCT patientProfileId) as patientCount
                    FROM PatientVisit
                    GROUP BY doctorId)

SELECT a.listName as provName, b.patientCount
FROM DoctorFacility as a
JOIN Patient_Count as b
ON b.doctorId = a.doctorFacilityId

尽管如此,doctorId真的等于doctorFacilityId吗?这似乎是在说,是的,那个医生,他实际上是一栋建筑。

我想他不想返回DoctorID。然后从查询的开始删除它,但将它保留在组中,具体取决于RDBMS的实现。IIRC,一些品牌的SQL数据库不喜欢按未出现在选择列表中的列进行分组。我不确定SQL Server是否是其中之一。SQL Server属于严格阵营。MySQL是虚构的。我认为Postgres更好,因为它处理函数依赖性…+1:通过ID聚合,然后额外加入以获取名称和其他元数据在我看来通常是最干净的。只有当元数据已经在聚合所需的表中时,我才会查看MAXname等。