我有许多处于各种状态的设备(本质上是“正在运行”或“关闭”,但还有其他状态)。每天结束时都会拍摄快照,以记录设备处于什么状态。我将COUNT个设备汇总为总体“正在运行”或“关闭”(例如,01月1日-726台CCTV正在“运行”)在01-01-18上有18台和4台CCTV处于“关闭”状态,在01-02-18上有728台CCTV正在“运行”,而在01-02-18上有2部CCTV在“下降”状态,等等。)
这是我当前的代码:
SELECT oper.failurecode AS 'Device Type',
COUNT(hist.status) AS 'Count',
hist.status AS 'Status',
CONVERT(DATE, DATEADD(MINUTE, -30, hist.datadatetime)) AS 'Date'
FROM locations loc
INNER JOIN locoper oper ON oper.location = loc.location
INNER JOIN serclochistory hist ON hist.location = loc.location
WHERE hist.status NOT IN ('DECOMMISSIONED', 'TRANSITION', 'NOT READY', 'NOT READY - Fiber')
AND CONVERT(TIME, hist.datadatetime) > '23:00:00'
GROUP BY
CONVERT(DATE, DATEADD(MINUTE, -30, hist.datadatetime)),
oper.failurecode,
hist.status
ORDER BY
CONVERT(DATE, DATEADD(MINUTE, -30, hist.datadatetime)),
oper.failurecode,
hist.status;
这给了我如下结果:
CCTV 6 DOWN 2018-01-01
CCTV 763 OPERATING 2018-01-01
CCTV 18 DOWN 2018-01-02
CCTV 748 OPERATING 2018-01-02
我想做的是合并该月的所有设备,以便看到如下结果:
CCTV 24 DOWN 2018-01
CCTV 1511 OPERATING 2018-01
我可以找到一些示例,这些示例说明如何将项目组合到一行,但不能以这种方式添加值。
答案 0 :(得分:0)
您的查询建议使用SQL Server
语法,则可以:
SELECT oper.failurecode AS 'Device Type', COUNT(hist.status) AS 'Count', hist.status AS 'Status', CONVERT(DATE, DATEADD(MINUTE, -30, hist.datadatetime)) AS 'Date'
FROM locations loc INNER JOIN
locoper oper
ON oper.location = loc.location INNER JOIN
serclochistory hist
ON hist.location = loc.location
WHERE hist.status NOT IN ('DECOMMISSIONED', 'TRANSITION', 'NOT READY', 'NOT READY - Fiber') AND CONVERT(TIME, hist.datadatetime) > '23:00:00'
GROUP BY CONVERT(VARCHAR(7), DATEADD(MINUTE, -30, hist.datadatetime), 120), oper.failurecode, hist.status
ORDER BY Date, oper.failurecode, hist.status;
答案 1 :(得分:0)
我很想使用通用表表达式(CTE)进行初始数据捕获。这样,您只需要转换一次日期值。阅读您的分组和排序也更加容易。
我不清楚是否需要从日期值中减去30分钟,但我认为其目的是捕获午夜30分钟左右的状态记录。您发布的查询不会执行此操作,因为时间过滤器未处于调整后的值。
无论如何-试一试。希望对您有所帮助。
;WITH statusFilteredRecords ([Device Type], [Status], [Date])
-- Set of records filtered by status, with the time adjustment of -30 minutes applied to the date.
AS
(
SELECT oper.failurecode AS 'Device Type',
hist.status AS 'Status',
DateAdd(MINUTE, -30, hist.dateadatetime) [Date] -- This normalises "End of Day" as being midnight +/- 30 minutes
FROM locations loc
INNER JOIN locoper oper
ON oper.location = loc.location
INNER JOIN serclochistory hist
ON hist.location = loc.location
WHERE hist.status NOT IN ('DECOMMISSIONED', 'TRANSITION', 'NOT READY', 'NOT READY - Fiber')
)
, eodFilteredRecords ([Device Type], [Status], [Date])
-- Set of records filtered by Time, so that only EOD records are included, with the date normalized to the first of the month for grouping
AS
(
SELECT [Device Type],
[Status],
CAST(DateAdd(dd, -(day([Date])-1), [Date]) as Date) AS [Date] -- Force the date to the first of the month.
FROM statusFilteredRecords
WHERE CONVERT(TIME, [Date]) > '23:00:00' -- Because we're operating on the normalized datetime value, this is really > 23:30 or < 00:30
)
SELECT [Device Type],
count([Status]) as [Count],
[Status],
[Date]
FROM eodFilteredRecords
GROUP BY [Device Type],
[Status],
[Date]
ORDER BY [Date],
[Device Type],
[Status]
<==编辑:回答OP要求解释的评论==>
Count()
是一个聚合函数-它对结果子组中的数据进行操作。
在这种情况下,子组是在[Device Type]
,[Status]
和[Date]
上匹配的子组-这是在查询的GROUP BY
子句中指定的。
GROUP BY [Device Type],
[Status],
[Date]
在原始查询中,GROUP BY
子句将字段DateTime
中的hist.dateadatetime
值转换为Date
值(没有时间分量)。删除值的 time 部分意味着给定 day 的所有值现在都相等,并且都属于同一子组。 ({01-Jan-2018 15:22:33
变成01-Jan-2018
,01-Jan-2018 22:51:00
等)。
GROUP BY
CONVERT(DATE, DATEADD(MINUTE, -30, hist.datadatetime)),
oper.failurecode,
hist.status
我要做的是进一步执行此步骤,以有效删除值的 time 部分和 day 部分,并将所有日期设置为第一个
CAST(DateAdd(dd, -(day([Date])-1), [Date]) as Date) AS [Date]
我们假设日期为2018年9月28日。我使用day([Date])
来获取月份中的某天(例如28),然后从该值中减去1(得出27),然后减去该天数,因此它会回到该月的第一天。
因此,现在,当我们评估GROUP BY [Device Type], [Status], [Date]
时,我们会将在同一 month 内发生的所有记录归为一组(11-Sep-2018
变成01-Sep-2018
, 30-Sep-2018
等。
将聚合函数Count()
应用于这些不太细粒度的记录组(将我的月份而不是日期分组)会得到您要查找的汇总结果。