对不在有子句中的列进行分组
Posted
技术标签:
【中文标题】对不在有子句中的列进行分组【英文标题】:group by on a column not present in having clause 【发布时间】:2013-02-27 06:52:47 【问题描述】:我有一个简单的 SQL 查询,其中包含 GROUP BY 、 HAVING 和 ORDER BY 子句。 HAVING 子句在 GROUP BY 中有一些我不想要的字段,这可能吗?因为我必须每小时对数据进行分组,并且在 HAVING 中有一个日期字段,所以分组无法正常工作。 代码是:
alter procedure [dbo].[sp_metadata_inflow]
@grp_name varchar(40) , @subgrp_name varchar(40)
as
begin
declare @i as int , @j as int,@k as int,@d as datetime , @m as datetime,@y as datetime;
set @d = datepart(day,'2012-12-13 10:54:55.000');
set @m = datepart(month,'2012-12-13 10:54:55.000');
set @y = datepart(YEAR,'2012-12-13 10:54:55.000');
set @i = 1;
set @j = @i - 1;
while (@i <=24)
begin
(SELECT top 5 @i,
ContactReason,
@grp_name,
@subgrp_name,
COUNT(*)
FROM [ISRM].[dbo].[ITSM01ISRM]
GROUP BY ContactReason,datepart(day,CreatedDate),CurrentGroup,CurrentSubGroup
HAVING (
datepart(day,CreatedDate)= @d AND datepart(MONTH,CreatedDate)= @m
AND datepart(year,CreatedDate) = @y AND datepart(hour,CreatedDate) <= @i
AND datepart(hour,CreatedDate) >=@j
)
AND (CurrentGroup = @grp_name) AND (CurrentSubGroup = @subgrp_name)
);
set @i = @i + 1;
set @j = @i -1;
end
end
go
【问题讨论】:
您能解释一下您的查询吗?我的意思是你想在实际中使用查询做什么? 所以,我想根据 Contact Reason(group by) 获取计数(*),对于一天中的每个小时......希望这是有道理的,我唯一的问题是我如何得到它无需在 group by 子句中编写 CreatedDate 在 mysql(尽管不是标准的 SQL)中,HAVING 子句中的列可能不在 GROUP BY 中。见dev.mysql.com/doc/refman/4.1/en/group-by-hidden-columns.html 我可以使用 where 和 group by 吗?我需要使用 SQL 您使用的是哪个 DBMS?问这个是因为 MySQL 中没有 DATEPART 函数。 Check this post 【参考方案1】:以下查询按小时对所有结果进行分组。为什么不希望在 GROUP BY 中有 CreatedDate?
SELECT
ContactReason,
CurrentGroup,
CurrentSubGroup,
dateadd(hour, datediff(hour, 0, CreatedDate), 0),
COUNT(1)
FROM [ISRM].[dbo].[ITSM01ISRM]
WHERE
(CurrentGroup = @grp_name) AND (CurrentSubGroup = @subgrp_name)
GROUP BY
ContactReason,
dateadd(hour, datediff(hour, 0, CreatedDate), 0),
CurrentGroup,
CurrentSubGroup;
【讨论】:
【参考方案2】:要真正回答您的问题,您似乎只想在 where 子句中使用这些条件。它看起来也很像 SQL-Server 语法,而不是标签所暗示的 MySQL。
同样值得注意的是,这是非常低效的:
(datepart(day,CreatedDate)= @d
AND datepart(MONTH,CreatedDate)= @m
AND datepart(year,CreatedDate) = @y
AND datepart(hour,CreatedDate) <= @i
AND datepart(hour,CreatedDate) >=@j )
在列上使用DATEPART
不仅会强制函数对每一行进行评估,还会消除列上任何索引的好处。最好写成Createddate >= '20130227 00:00' AND CreatedDate < '20130227 01:00'
。
此外,您在每个循环中执行 2 小时,这听起来不像预期的行为。
最后,我无法想象返回 24 个结果集是处理数据的最佳方式,如果您想要每小时计算一次,将小时作为列并执行一个查询并返回一个数据集是否没有意义?
例如
| ContactReason | GroupName | SubGroupName | 00:00 | 01:00 | 02:00 | 03:00 |.....| 23:00 |
|----------------+------------+--------------+-------+-------+-------+-------+.....+-------|
| Example Reason | Test Group | Sub Group | 5 | 10 | 8 | 1 |.....| 14 |
| Another Reason | Test Group | Sub Group | 3 | 1 | 13 | 8 |.....| 23 |
在这种情况下,您的查询可以写成
DECLARE @Date DATETIME = '20121213';
WITH Data AS
( SELECT ContactReason,
GroupName = @grp_name,
SubGroupName = @subgrp_name,
CreatedHour = CAST(DATEADD(HOUR, DATEDIFF(HOUR, 0, Createddate), 0) AS TIME),
[Value] = 1
FROM [ISRM].[dbo].[ITSM01ISRM]
WHERE CurrentGroup = @grp_name
AND CurrentSubGroup = @subgrp_name
AND CreatedDate >= @Date
AND CreatedDate < DATEADD(DAY, 1, @Date)
)
SELECT *
FROM Data
PIVOT
( COUNT(Value)
FOR CreatedHour IN
( [00:00], [01:00], [02:00], [03:00], [04:00], [05:00],
[06:00], [07:00], [08:00], [09:00], [10:00], [11:00],
[12:00], [13:00], [14:00], [15:00], [16:00], [17:00],
[18:00], [19:00], [20:00], [21:00], [22:00], [23:00]
) pvt;
【讨论】:
以上是关于对不在有子句中的列进行分组的主要内容,如果未能解决你的问题,请参考以下文章