June 7, 2011 at 9:54 am
I have the following query:
WITH
Starts as
(SELECT id, date_time
FROM events
WHERE on_code = 1),
Ends as
(SELECT id, date_time
FROM events
WHERE off_code = 2)
SELECT DISTINCT a.id, a.date_time
FROM tbl_1 a
INNER JOIN Starts
ON a.id = Starts.id
INNER JOIN Ends
ON a.id = Ends.id
WHERE
a.date_time
BETWEEN
Starts.date_time
AND
Ends.date_time
ORDER BY a.date_time
which I use to retrieve an ID and date/time field from an events table to allow me to then cross reference other fields in different tables that occur only between the on_code and off_code times. This use of a CTE works perfectly for me if there is only one entry per ID field. However, on occassions the events table has multiple on and off events which means that the CTE tables "Starts" and "Ends" have multiple start and stop date/time fields for the one ID field. If I then use this query to cross reference other tables, based on the ID field, in the "where date_time between..." clause I get all records between the first start time record in "Starts" and the last stop time on "Ends". What I actually want in these cases of multiple start/stop events is just those records that occur between all of the multiple start/stop times.
I'm not sure if the use of a CTE is appropriate in this scenario but if so how do I start re-writing the code. I'm wondering if I need to put a loop in but I'm stumped about where to begin.
Thank you for any help you can offer.
Ian.
June 7, 2011 at 10:16 am
Please post DDL for your tables, DML to add some test data that lets your query demonstrate the problem, and your expected results. If you're not sure what I mean please refer to this article:
http://www.sqlservercentral.com/articles/Best+Practices/61537/[/url]
There are no special teachers of virtue, because virtue is taught by the whole community.
--Plato
June 7, 2011 at 10:20 am
I agree with OPC - we need the things he requested so we can better assess and test the issue and solution.
Jason...AKA CirqueDeSQLeil
_______________________________________________
I have given a name to my pain...MCM SQL Server, MVP
SQL RNNR
Posting Performance Based Questions - Gail Shaw[/url]
Learn Extended Events
June 7, 2011 at 10:30 am
OK will do, thanks.
Ian.
June 7, 2011 at 4:27 pm
Apologies for my delay but here is my DDL and DML which I hope I have presented correctly. I have also re-written the CTE at the end of the code which needed a slight modification.
If I need to supply any further information please let me know and I'll happily oblige. I'm sorry that I can't offer any solutions I've tried as I don't know where to start with this.
Thanks again for looking at my problem.
Ian
---- If the tables exists drop them
IF OBJECT_ID('events') IS NOT NULL
DROP TABLE events
IF OBJECT_ID('tbl_1') IS NOT NULL
DROP TABLE tbl_1
---- Create test tables with
CREATE TABLE events
(
PK INT PRIMARY KEY CLUSTERED,
ID INT,
DATE_TIME DATETIME,
EV_CODE INT
)
CREATE TABLE tbl_1
(
PK INT PRIMARY KEY CLUSTERED,
ID INT,
DATE_TIME DATETIME
)
--- This table, tbl_1 has more fields but are not required to
--- demonstrate my problem
----- Insert the test data into the test tables
INSERT INTO events
(PK, ID, DATE_TIME, EV_CODE)
SELECT '1', '1', '2011-06-07 10:10:30.000', '1' UNION ALL
SELECT '2', '1', '2011-06-07 10:20:30.000', '2' UNION ALL
SELECT '3', '1', '2011-06-07 10:25:30.000', '1' UNION ALL
SELECT '4', '1', '2011-06-07 10:40:30.000', '2' UNION ALL
SELECT '5', '1', '2011-06-07 10:45:30.000', '1' UNION ALL
SELECT '6', '1', '2011-06-07 10:55:30.000', '2' UNION ALL
SELECT '7', '2', '2011-06-07 12:10:30.000', '1' UNION ALL
SELECT '8', '2', '2011-06-07 12:50:30.000', '2'
---- EV_CODE 1 = ON; EV_CODE 2 = OFF
---- MULTIPLE ON/OFF EVENTS CAN OCCUR FOR ONE ID eg: ID = 1
INSERT INTO tbl_1
(PK, ID, DATE_TIME)
SELECT '1', '1', '2011-06-07 10:12:30.000' UNION ALL
SELECT '2', '1', '2011-06-07 10:16:30.000' UNION ALL
SELECT '3', '1', '2011-06-07 10:22:30.000' UNION ALL
SELECT '4', '1', '2011-06-07 10:24:30.000' UNION ALL
SELECT '5', '1', '2011-06-07 10:28:30.000' UNION ALL
SELECT '6', '1', '2011-06-07 10:34:30.000' UNION ALL
SELECT '7', '1', '2011-06-07 10:38:30.000' UNION ALL
SELECT '8', '1', '2011-06-07 10:42:30.000' UNION ALL
SELECT '9', '1', '2011-06-07 10:44:30.000' UNION ALL
SELECT '10', '1', '2011-06-07 10:48:30.000' UNION ALL
SELECT '11', '1', '2011-06-07 10:52:30.000' UNION ALL
SELECT '12', '1', '2011-06-07 10:54:30.000' UNION ALL
SELECT '13', '2', '2011-06-07 12:08:30.000' UNION ALL
SELECT '14', '2', '2011-06-07 12:12:30.000' UNION ALL
SELECT '15', '2', '2011-06-07 12:20:30.000' UNION ALL
SELECT '16', '2', '2011-06-07 12:30:30.000' UNION ALL
SELECT '17', '2', '2011-06-07 12:40:30.000' UNION ALL
SELECT '18', '2', '2011-06-07 12:52:30.000'
---- FOR ID = 1 THERE ARE 12 RECORDS THAT OCCUR BETWEEN
---- THE FIRST ON EVENT AND THE LAST OFF EVENT BUT I ONLY
---- WANT THE RECORDS THAT FALL DURING AN ON PERIOD WHICH
---- IS JUST 8 RECORDS (PK: 1,2,5,6,7,10,11 AND 12 IN tbl_1)
---- FOR ID = 2 THERE ARE 6 TOTAL RECORDS BUT ONLY 4
---- ARE INCLUSIVE OF THE ON/OFF EVENTS AND THIS IS THE
---- EXPECTED RESULT.
WITH
Starts as
(SELECT id, date_time
FROM events
WHERE ev_code = 1),
Ends as
(SELECT id, date_time
FROM events
WHERE ev_code = 2)
SELECT DISTINCT a.id, a.date_time
FROM tbl_1 a
INNER JOIN Starts
ON a.id = Starts.id
INNER JOIN Ends
ON a.id = Ends.id
WHERE
a.date_time
BETWEEN
Starts.date_time
AND
Ends.date_time
ORDER BY a.date_time
June 7, 2011 at 4:44 pm
eyejay (6/7/2011)
If I then use this query to cross reference other tables, based on the ID field, in the "where date_time between..." clause I get all records between the first start time record in "Starts" and the last stop time on "Ends". What I actually want in these cases of multiple start/stop events is just those records that occur between all of the multiple start/stop times.
Could you clarify this for me? I'm reading those sentences to mean the same thing.
If you could provide sample output, that would be great.
Jason...AKA CirqueDeSQLeil
_______________________________________________
I have given a name to my pain...MCM SQL Server, MVP
SQL RNNR
Posting Performance Based Questions - Gail Shaw[/url]
Learn Extended Events
June 7, 2011 at 5:22 pm
I read through your notes in the script and think I may have something that will work.
WITH timeframes AS
(SELECT es.id, es.date_time StartTime,EE.date_time AS EndTime
FROM events ES
CROSS APPLY (SELECT PK,id, date_time
FROM events
WHERE ev_code = 2
) EE
WHERE ES.ev_code = 1
AND ES.id = EE.id
AND EE.date_time > es.date_time
AND ES.PK = EE.pk - 1
)
SELECT DISTINCT a.id, a.date_time
FROM tbl_1 a
INNER JOIN timeframes tf
ON a.id = tf.id
WHERE a.date_time BETWEEN tf.StartTime AND tf.EndTime
ORDER BY a.date_time
Jason...AKA CirqueDeSQLeil
_______________________________________________
I have given a name to my pain...MCM SQL Server, MVP
SQL RNNR
Posting Performance Based Questions - Gail Shaw[/url]
Learn Extended Events
June 7, 2011 at 5:28 pm
Thanks for getting back to me and I will post my expected output, but to try and clarify, currently in a multiple on/off scenario I get all records that have a time between the first start event and the last stop event including those records when the events timer is off. I only want the records when the timer is on, so only between an on then off ev_code and not the records between the off and subsequent on ev_code. Hope this is a bit clearer and will post some expected output but it will be tomorrow now before I get chance (UK bedtime 🙂 ).
Many thanks,
Ian
June 7, 2011 at 5:32 pm
While working on that, please check the last script I posted and see if that works.
Jason...AKA CirqueDeSQLeil
_______________________________________________
I have given a name to my pain...MCM SQL Server, MVP
SQL RNNR
Posting Performance Based Questions - Gail Shaw[/url]
Learn Extended Events
June 8, 2011 at 2:46 am
Try this
WITH StartAndEnds(id,Start_date_time,End_date_time) AS (
SELECT s.id,s.date_time,MIN(e.date_time)
FROM events s
INNER JOIN events e ON e.id=s.id AND e.date_time>=s.date_time AND e.ev_code = 2
WHERE s.ev_code = 1
GROUP BY s.id,s.date_time)
SELECT t.pk,t.id,t.date_time
FROM tbl_1 t
WHERE EXISTS (SELECT * FROM StartAndEnds s
WHERE s.id=t.id
AND t.date_time BETWEEN s.Start_date_time AND s.End_date_time)
ORDER BY t.date_time;
____________________________________________________
Deja View - The strange feeling that somewhere, sometime you've optimised this query before
How to get the best help on a forum
http://www.sqlservercentral.com/articles/Best+Practices/61537June 8, 2011 at 3:55 am
Jason and Mark,
Both of your solutions work perfectly, thank you so much for taking time to look at my problem and help out. I've learnt something new.
Cheers,
Ian.
June 8, 2011 at 9:36 am
Most excellent. Glad it works.
Jason...AKA CirqueDeSQLeil
_______________________________________________
I have given a name to my pain...MCM SQL Server, MVP
SQL RNNR
Posting Performance Based Questions - Gail Shaw[/url]
Learn Extended Events
Viewing 12 posts - 1 through 11 (of 11 total)
You must be logged in to reply to this topic. Login to reply