简体   繁体   English

给定日期范围内每天的设备计数

[英]Count devices per day in a given date range

I have a table which has devices with 3 statuses, Pass, Fail and Warning.我有一个表,其中包含具有 3 种状态的设备,通过、失败和警告。

Device设备 Status地位 Date日期
Device1设备1 Pass经过 12/1/2020 2020 年 12 月 1 日
Device2设备2 Fail失败 12/1/2020 2020 年 12 月 1 日
Device3设备3 Warning警告 12/1/2020 2020 年 12 月 1 日
Device1设备1 Fail失败 12/2/2020 2020 年 12 月 2 日
Device2设备2 Warning警告 12/2/2020 2020 年 12 月 2 日
Device3设备3 Pass经过 12/2/2020 2020 年 12 月 2 日

I want to generate a trend graph of count of devices based on the daily status.我想根据日常状态生成设备数量的趋势图。 The count is on all the devices for each day.每天在所有设备上进行计数。 The table above will have device data repeated for multiple dates.上表将重复多个日期的设备数据。

Example: I want to generate a stacked bar graph, which will show count of devices which are pass, fail or warning.示例:我想生成一个堆叠条形图,它将显示通过、失败或警告的设备数量。 Need to get a query which I can use to get the response back with DateTime , count of failed devices, count of devices passed, count of devices having warning over a range of dates.需要获取一个查询,我可以使用它来获取返回响应DateTime 、失败设备的数量、通过的设备数量、在一定日期范围内发出警告的设备数量。

select * (select count(*) from status_table where overall_status = 'Fail' and startDate > "" and endDate < "") as failedCount,
(select count(*) from status_table  where overall_status = 'Warning' and startDate > "" and endDate < "") as WarningCount,
(select count(*) from status_table  where overall_status = 'Pass'  startDate > "" and endDate < "") as passCount from status_table

Is there a better solution?有更好的解决方案吗?

You can use the aggregate FILTER clause to do it in a single query.您可以使用聚合FILTER子句在单个查询中执行此操作。

This gets three counts (fail, pass, warn) for every selected device on every day in the selected date range.这会在所选日期范围内的每一天为每个所选设备获取三个计数(失败、通过、警告)。 A count of NULL for days without any appearance. NULL 数天没有出现。 0 if the device appeared, but not with this status: 0 如果设备出现,但不处于此状态:

SELECT date, device_name
     , fail_count, warning_count, pass_count
FROM  (SELECT DISTINCT device_name FROM status_table) d  -- all devices ①
CROSS  JOIN (
   SELECT generate_series(timestamp '2020-12-01'
                        , timestamp '2020-12-31'
                        , interval  '1 day')::date
   ) t(date)  -- all dates
LEFT   JOIN (
   SELECT date, device_name
        , count(*) FILTER (WHERE overall_status = 'Fail')    AS fail_count
        , count(*) FILTER (WHERE overall_status = 'Warning') AS warning_count
        , count(*) FILTER (WHERE overall_status = 'Pass')    AS pass_count 
   FROM   status_table
   WHERE  date >= '2020-12-01'  -- same date range as above
   AND    date <= '2020-12-31'
   GROUP  BY 1, 2
   ) s USING (date, device_name)
ORDER  BY 1, 2;

Basically, you CROSS JOIN all devices to all dates (Cartesian product), the append data where data can be found with a LEFT JOIN .基本上,您CROSS JOIN所有设备到所有日期(笛卡尔积),append 数据可以通过LEFT JOIN找到数据。

① Since you don't seem to have a device table (which you probably should), generate the full list on the fly. ① 由于您似乎没有device表(您可能应该),因此请即时生成完整列表。 The above query with DISTINCT is good for few rows per device.上面带有DISTINCT的查询适用于每个设备的几行。 Else, there are (much) faster techniques like:否则,有(很多)更快的技术,例如:

WITH RECURSIVE cte AS (
   (SELECT device_name FROM status_table ORDER BY 1 LIMIT 1)
   UNION ALL
   SELECT (SELECT device_name FROM status_table
           WHERE  device_name > t.device_name ORDER BY 1 LIMIT 1)
   FROM   cte
   WHERE  device_name IS NOT NULL
   )
SELECT * FROM cte
WHERE  device_name IS NOT NULL;

See:看:

The subquery s aggregates only rows from the given date range.子查询s仅聚合给定日期范围内的行。 It's strictly optional.它是严格可选的。 You can also left-join to the underlying table directly, and then aggregate all.您也可以直接左连接到基础表,然后聚合所有。 But this approach is typically (much) faster.但是这种方法通常(很多)更快。

You can convert NULL to zero or vice versa with COALESCE / NULLIF .您可以使用COALESCE / NULLIF将 NULL 转换为零,反之亦然。

Related:有关的:

For more flags, a crosstab() query might be faster.对于更多标志, crosstab()查询可能会更快。 See:看:

About generating a date range:关于生成日期范围:

Be aware that dates are defined by your current time zone setting if you operate with timestamp with time zone .请注意,如果您使用timestamp with time zone操作,则日期是由您当前的时区设置定义的。 See:看:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM