| Author |
Topic |
|
Sitka
Aged Yak Warrior
571 Posts |
Posted - 2011-03-15 : 10:00:52
|
| [code]--I think this query is like what would be used in a phone call or other service billing situation.--I've seen this type of record keeping in some clockin clockout applications as well.--The main difficulty is that as opposed to the more usual record which would have a starttime and an endtime--for each row, this data utilizes a sequence of stops and starts events which aren't necessarily paired.--this table represents a compilaton of various logs from machines--throughout the enterprise, for this example only one machine is includedCREATE TABLE machines( machine nchar(10) NOT NULL, datexxx datetime NOT NULL, maincommand nchar(10) NOT NULL, secondarycommand nvarchar(50) NULL, idxxx int IDENTITY(1,1) NOT NULL, CONSTRAINT PK_machines PRIMARY KEY CLUSTERED ( idxxx ASC ))SET IDENTITY_INSERT machines ONINSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-13 00:00:01.000','Start','sadsda',1)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-13 03:12:15.000','Stop','wertty',2)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-13 04:26:39.000','Start','mjuidfhelwst dsd 000 nhdy',3)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-13 07:08:51.500','Stop','jo is cool',25)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-13 12:21:20.000','Start','X$$$$HEX)*(',5)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-13 13:40:11.000','Stop','st',6)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-13 19:56:28.250','Start','123456',7)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-13 23:17:39.000','Start','NULL',8)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-13 23:33:11.000','Stop','jebesus',9)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-14 01:26:39.000','Stop','NULL',10)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-14 01:26:42.000','Stop','90',11)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-14 12:39:00.000','Start','NULL',12)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-14 14:02:00.000','Stop','NULL',111)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-14 17:26:39.000','Start','a loop 900',14)INSERT INTO machines (machine, datexxx, maincommand, secondarycommand,idxxx) VALUES ('dia01','2011-03-14 19:07:01.000','Stop','NULL',15)SET IDENTITY_INSERT machines OFF--TRUNCATE TABLE machinesSELECT machine ,datexxx ,maincommand ,secondarycommand ,idxxx FROM machines ORDER BY datexxx--The above information would have an intermediate result shown below but at Time0 there is no--result for the first row, That is no counting duration.--The numeric value is seconds between starts and stops and stops and stops and starts and starts--The change in a maincommand defines the duration, not the value of the maincommand and each row--needs to reference the previous state of the machine--Up is Uptime--Dn is downtime/*11534 Up4464 Dn9732.5 Up18748.5 Dn4731 Up22577.25 Dn12070.75 Up931.9999997 Up6808 Dn3.000000073 Dn40338 Dn4980 Up12279 Dn6022 Up*/--the final desired result is--secondsofUP secondsofDN--50002.25 105217.75[/code]The exact Start and Stop logic is very simple. Start followed by Stop would be a datediff in seconds between the two datexxx values of the two rows.Start followed by one or more Starts means there is no change, the machine continues to run. Same with multiple Stops.The sequence order is datexxx based, it is the change in maincommand that flips the state of the machine from Started and Stopped."it's definitely useless and maybe harmful". |
|
|
Sitka
Aged Yak Warrior
571 Posts |
Posted - 2011-03-15 : 11:47:30
|
I think this gets rid of the nonessential rows. What is a nonessential row? One where the state of the machine does not change because the maincommand is not different than the previous maincommand.I think just repeat this conditional concept, WHERE D.rank = C.rank - 1 to widen the rows to contain a start AND a stop datexxx then it becomes a typical datediff aggregate query.SELECT E.rankleft,E.machineleft,E.datexxxleft,E.maincommandleftFROM( SELECT C.rank as rankleft,C.machine as machineleft,C.datexxx as datexxxleft,C.maincommand as maincommandleft ,D.rank as rankright,D.machine as machineright,D.datexxx as datexxxright,D.maincommand as maincommandright FROM ( SELECT rank() OVER (ORDER BY A.datexxx) as rank, A.[machine] ,A.datexxx ,A.maincommand FROM machines A ) C CROSS JOIN ( SELECT rank() OVER (ORDER BY A.datexxx) as rank, A.machine ,A.datexxx ,A.maincommand FROM machines A ) D WHERE D.rank = C.rank - 1 AND C.maincommand <> D.maincommand)EUNIONSELECT TOP 1 rank() OVER (ORDER BY F.datexxx) as rank, F.machine,F.datexxx,F.maincommand FROM machines F "it's definitely useless and maybe harmful". |
 |
|
|
Sitka
Aged Yak Warrior
571 Posts |
Posted - 2011-03-16 : 10:26:24
|
This at least proves I can get most of the requirements I've been given so far.It returns the running time and notrunning time in seconds for a machine for one day.I don't know yet how the first boundary conditions are exactly going to be met. The data will propabably end up being continuous day to day so I will probably have to look back in time to resolve the beginning state of the machine.SELECT P.machine, SUM( DATEDIFF(ss,P.leftdate, P.rightdate) ) as duration, P.runstate--SELECT P.machine, DATEDIFF(ss,P.leftdate, P.rightdate) as duration, P.runstateFROM( SELECT W.rowxxx, W.machineleft as machine, W.datexxxleft as leftdate, --COALESCE(Z.datexxxleft, CAST(convert(varchar, getdate(), 112)+' 23:59:59' as datetime)) as rightdate, COALESCE(Z.datexxxleft, '2011-03-14 19:07:00.000') as rightdate, CASE W.maincommandleft WHEN 'Start' THEN 'Up' ELSE 'Dn' END as runstate FROM ( SELECT ROW_NUMBER() OVER (ORDER BY X.datexxxleft) as rowxxx, X.machineleft, X.datexxxleft, X.maincommandleft FROM ( SELECT E.rankleft,E.machineleft,E.datexxxleft,E.maincommandleft FROM ( SELECT C.rank as rankleft,C.machine as machineleft,C.datexxx as datexxxleft,C.maincommand as maincommandleft ,D.rank as rankright,D.machine as machineright,D.datexxx as datexxxright,D.maincommand as maincommandright FROM ( SELECT rank() OVER (ORDER BY A.datexxx) as rank, A.[machine] ,A.datexxx ,A.maincommand FROM machines A ) C CROSS JOIN ( SELECT rank() OVER (ORDER BY A.datexxx) as rank, A.machine ,A.datexxx ,A.maincommand FROM machines A ) D WHERE D.rank = C.rank - 1 AND D.maincommand <> C.maincommand ) E UNION SELECT TOP 1 rank() OVER (ORDER BY F.datexxx) as rank, F.machine ,F.datexxx ,F.maincommand FROM machines F ) X ) W LEFT JOIN ( SELECT ROW_NUMBER() OVER (ORDER BY Y.datexxxleft) as rowxxx, Y.machineleft, Y.datexxxleft FROM ( SELECT E.rankleft,E.machineleft,E.datexxxleft,E.maincommandleft FROM ( SELECT C.rank as rankleft,C.machine as machineleft,C.datexxx as datexxxleft,C.maincommand as maincommandleft ,D.rank as rankright,D.machine as machineright,D.datexxx as datexxxright,D.maincommand as maincommandright FROM ( SELECT rank() OVER (ORDER BY A.datexxx) as rank, A.[machine] ,A.datexxx ,A.maincommand FROM machines A ) C CROSS JOIN ( SELECT rank() OVER (ORDER BY A.datexxx) as rank, A.machine ,A.datexxx ,A.maincommand FROM machines A ) D WHERE D.rank = C.rank - 1 AND D.maincommand <> C.maincommand ) E UNION SELECT TOP 1 rank() OVER (ORDER BY F.datexxx) as rank, F.machine ,F.datexxx ,F.maincommand FROM machines F ) Y ) Z ON W.rowxxx = Z.rowxxx - 1)PGROUP BY P.machine,P.runstate "it's definitely useless and maybe harmful". |
 |
|
|
|
|
|