【发布时间】:2019-02-08 17:57:32
【问题描述】:
我已经发生了几次以下情况,我的解决方案感觉很粗糙。
一般来说,我的表格可能如下所示:
WorkOrder:
WorkOrderID (primary key)
WorkOrderDesc
Process:
ProcessID (primary key)
ProcessDesc
Work:
ProcessID
WorkOrderID
我想知道一个工单上完成了多少个流程,所以我做了类似的事情
select w.WorkOrderId,w.ProcessID,Count(*)
from Work as w
inner join WorkOrder as wo on w.WorkOrderID=wo.WorkOrderID
inner join Process as p on w.ProcessID = p.ProcessID
group by w.WorkOrderID,w.ProcessID
此代码将告诉我每个流程在每个工单上运行了多少次。
我遇到的问题是我真的不希望查询结果成为索引,我希望它成为描述,因为这些将被报告或绘制。因为它是 group by 我知道 WorkOrderID 和 ProcessID 是独一无二的这些条目的最大值(或最小值)。
select w.WorkOrderId,w.ProcessID,Count(*),Max(w.WorkOrderDesc),Max(p.ProcessDesc)
from Work as w
inner join WorkOrder as wo on w.WorkOrderID=wo.WorkOrderID
inner join Process as p on w.ProcessID = p.ProcessID
group by w.WorkOrderID,w.ProcessID
这个查询给了我 ID,就像第一个查询一样,但它也填写了描述。
有没有办法在不使用这个 hack 的情况下将这种类型的查询作为单个查询?我知道我可以使用 CTE 将第一个查询的结果第二次加入以从两个表中获取描述,但这似乎最终会再次运行相同的(ish)查询。
查询引擎似乎可以检测到我正在按主键进行分组,并允许我在 select 语句中从该行中选择项目。
注意:我意识到我可以只使用这个玩具示例中的描述来完成查询,在一个真实的示例中,每个查询都会在查询中报告许多项目,这些项目都来自连接的表。
【问题讨论】:
-
不知道你所说的黑客是什么意思;你写的只是一个聚合查询。但是(如果我理解您要正确说的话)不,T-SQL 不支持隐含的
GROUP BY语句。您必须明确说明要聚合的值以及聚合的值。 -
如果我知道它们都是相同的,因为它们都来自我使用主键分组的表,那么 SQL 引擎也应该看到这一点。似乎可以证明,当按主键分组时,可以安全地选择主键表中行中的每个值,而无需使用 Max() 或 Min() 修饰它或运行第二个查询。
-
如果它们都相同,则包括
GROUP BY中的列。 T-SQL 旨在不允许隐含的GROUP BY语句,它们必须是显式的。如果您从GROUP BY中省略一列并且不使用聚合函数将其包围,那么您将收到错误消息。它们是 T-SQL 的设计方式。如果您对该功能不满意,您将不得不使用允许这种语法的不同 RDBMS;比如 MySQL。您所说的行为不太可能(很快)会改变;它肯定不在 SQL Server 2019 Preview 中。 -
为什么不将 w.WorkOrderDesc 添加到 group by 并将其从聚合中删除?它不会给出相同的结果吗?它应该,如果它也真的很独特的话
-
@Larnu,这并不是“隐含的分组依据”。如果我按唯一键分组,则由该键定义的行的元素是唯一的,并且可以安全地添加到 select 语句中,没有歧义。看来这不是 tsql 的特性。 (你应该写一个你不能用tsql回答这个问题)
标签: sql-server tsql