我无法找到解决此问题的好方法。我有一个如下所示的数据集:
MACHINE DATETIME CODE C54118PC1 2016-04-01 00:00:01.000 10 C54118PC1 2016-04-01 00:01:12.000 4 C54118PC1 2016-04-01 00:01:36.000 10 C54118PC1 2016-04-01 00:01:50.000 4 C54123PC1 2016-04-01 00:00:02.000 0 C54123PC1 2016-04-01 01:00:02.000 0
最终,我希望在Qlikview文档中将其显示为饼图,显示机器在每个州(代码)中花费的时间。
为了做到这一点,我想我需要以这种格式获取数据:
MACHINE DATE CODE DURATION Machine1 07/06/2016 2 07:30:14 Machine1 07/06/2016 5 02:45:10 Machine2 07/06/2016 0 12:37:05 Machine2 07/06/2016 5 04:04:59 Machine1 08/06/2016 2 02:57:13 Machine1 08/06/2016 4 04:12:05 Machine1 08/06/2016 5 03:07:12 Machine3 08/06/2016 8 02:49:23
对于每台机器,每台机器的每行代码为1行,包含当天的总持续时间和代码。
另一个考虑因素是这是一个大型数据集 - 目前至少有200万行,随着更多机器的添加和更多时间的推移,这可能会很快增长。
所以,基本上我需要一种非常有效的方法来计算在不同状态(代码)中花费的时间,按机器和日期。我认为这最好在SQL中完成,但是我也可以在Qlikview中做到这一点,如果这样做更有效率。有人可以帮忙吗?
提前谢谢!
编辑:对不起,我忘了解释日志记录是如何工作的!我们有一堆机器在白天在各种状态之间交替(例如打印,空闲,清洁)。每次它们改变状态(例如从打印到空闲)时,它们都会记录时间戳以及它们的新状态。
(它们还会定期记录时间戳及其当前状态,即使它们实际上没有改变状态。)
持续时间计算为两个连续时间戳之间的时差。
答案 0 :(得分:0)
UNTESTED:
LEAD()
一个分析(窗口函数),可以让你查看给定数据分区的下一个有序行值,看起来它会起作用......
所以在这种情况下:我们想要给定机器的下一行的日期时间,而不管状态......如下:
SELECT MACHINE
, FORMAT(DATETIME, 'DD/MM/YYYY')
, CODE
, SUM(Lead(DateTIme) over (partition by Machine order by dateTime asc) - datetime) AS DURATION,
FROM TABLENAME
GROUP BY MACHINE, CODE, FORMAT(DATETIME, 'DD/MM/YYYY')
我不确定这里的数据数学是为了获得持续时间。
答案 1 :(得分:0)
试试这个
Declare @Table table (machine varchar(25),DateTime datetime,Code int)
Insert into @Table (Machine,DateTime,Code) values
('Machine1','2016-04-01 00:00:01.000',10),
('Machine1','2016-04-01 00:01:12.000',4),
('Machine1','2016-04-01 00:01:36.000',10),
('Machine1','2016-04-01 00:01:50.000',4),
('Machine2','2016-04-01 00:00:02.000',0),
('Machine2','2016-04-01 01:00:02.000',0),
('Machine1','2016-04-02 00:00:01.000',10),
('Machine1','2016-04-02 00:01:12.000',4),
('Machine1','2016-04-02 00:01:36.000',10),
('Machine1','2016-04-02 00:01:50.000',4),
('Machine2','2016-04-02 00:00:02.000',0),
('Machine2','2016-04-02 01:00:02.000',0)
IF OBJECT_ID('tempdb.dbo.#Temp1', 'U') IS NOT NULL
DROP TABLE #Temp1;
-- Generate Date Range
Select Distinct DateR1=cast(DateTime as Date),DateR2=DateAdd(DD,1,cast(DateTime as Date)) into #Temp1 from @Table
Create Index idx on #Temp1 (DateR1,DateR2)
;with cteBase as (
Select *
,MSDate1 = DateTime
,MSDate2 = Lead(DateTime,1,DateAdd(DD,1,cast(DateTime as Date))) over (Partition by Machine Order by Machine,DateTime)
From @Table
)
Select Machine
,Date = DateR1
,Code
,Duration = CONVERT(varchar, DATEADD(SS, sum(DateDiff(SS,case when MSDate1<=DateR1 then DateR1 else MSDate1 end,case when MSDate2>DateR2 then DateR2 else MSDate2 end)), 0), 114)
From #Temp1 A
Join cteBase B on (MSDate1 between DateR1 and DateR2 or MSDate2 between DateR1 and DateR2)
Group By Machine
,DateR1
,Code
返回
Machine Date Code Duration
Machine1 2016-04-01 4 23:58:34:000
Machine1 2016-04-01 10 00:01:25:000
Machine1 2016-04-02 4 23:58:35:000
Machine1 2016-04-02 10 00:01:25:000
Machine2 2016-04-01 0 23:59:58:000
Machine2 2016-04-02 0 00:00:00:000
答案 2 :(得分:0)
这可以在QV本身轻松实现(参见下面的脚本)。
关于数据大小。您可以在QV中实现Incremental Load
并在重新加载应用时仅加载新记录,并仅在小集上执行转换,而不是在完整数据集上执行转换。
示例工作流程将:在每次重新加载时仅提取最后日期的记录,执行转换,从qvd加载先前转换的数据并将新结果连接到qvd。这是QV非常常见的方法(我每天使用它)。通常我更喜欢这种方法,因为我不会推动数据库进行QV的工作并避免与DBA发生冲突;)
如果你想我可以使用增量加载粘贴样本脚本(只需留下评论)
有关增量加载的更多详细信息:
示例脚本:
RawData:
Load
MACHINE,
// DATETIME, // this is not needed anymore
CODE,
date(left(DATETIME, 10)) as Date, // extract the date
mid(DATETIME, 12, 8) as Duration // extract the duration
;
Load * Inline [
MACHINE , DATETIME , CODE
C54118PC1 , 2016-04-01 00:00:01.000 , 10
C54118PC1 , 2016-04-01 00:01:12.000 , 4
C54118PC1 , 2016-04-01 00:01:36.000 , 10
C54118PC1 , 2016-04-01 00:01:50.000 , 4
C54123PC1 , 2016-04-01 00:00:02.000 , 0
C54123PC1 , 2016-04-01 01:00:02.000 , 0
];
Data:
Load
interval(sum(Duration)) as TotalDuration, // sum the total duration and convert it to timestamp format
MACHINE,
Date,
CODE
Resident
RawData
Group By
MACHINE,
Date,
CODE
;
Drop Table RawData; // this table is not needed anymore