I would like to create a temp table from the below table.
------------------------|--------
Date | Length
------------------------|--------
2014-08-28 00:00:00.000 | 1.5
2014-08-28 00:00:00.000 | 2.6
2014-08-28 00:00:00.000 | 1.5
2014-08-28 00:00:00.000 | 3.3
2014-08-28 00:00:00.000 | 1.1
2014-08-28 00:00:00.000 | 8.5
2014-08-28 00:00:00.000 | 8.6
2014-08-28 00:00:00.000 | 11.3
And have the temp table look like the one below.
Date | Length | Length_Range
------------------------|---------|--------------
2014-08-28 00:00:00.000 | 1.5 | 1-4
2014-08-28 00:00:00.000 | 2.6 | 1-4
2014-08-28 00:00:00.000 | 6.5 | 5-10
2014-08-28 00:00:00.000 | 3.3 | 1-4
2014-08-28 00:00:00.000 | 1.1 | 1-4
2014-08-28 00:00:00.000 | 8.5 | 5-10
2014-08-28 00:00:00.000 | 8.6 | 5-10
2014-08-28 00:00:00.000 | 11.3 | 11-15
I would like to be able to define the [Length_Range].
Microsoft SQL Server 2016.
Compatibility level: SQL Server 2005 (90)
Use case:
select t.*,
(case when length >= 1 and length < 4 then '1-4'
when length < 10 then '5-10'
when length < 15 then '11-15'
else '16+'
end) as length_range
into #temp_t
from t;
CREATE TABLE #TABLE1
([DATE] DATETIME, [LENGTH] FLOAT)
INSERT INTO #TABLE1
([DATE], [LENGTH])
VALUES
('2014-08-28 00:00:00', 1.5),
('2014-08-28 00:00:00', 2.6),
('2014-08-28 00:00:00', 1.5),
('2014-08-28 00:00:00', 3.3),
('2014-08-28 00:00:00', 1.1),
('2014-08-28 00:00:00', 8.5),
('2014-08-28 00:00:00', 8.6),
('2014-08-28 00:00:00', 1.3)
SELECT *,CASE
WHEN LENGTH BETWEEN 1 AND 4 THEN '1-4'
WHEN LENGTH BETWEEN 5 AND 10 THEN '5-10'
WHEN LENGTH BETWEEN 11 AND 15 THEN '11-15' END AS LENGHT_RANGE
FROM #TABLE1
OUTPUT
Date Length LENGHT_RANGE
2014-08-28 00:00:00.000 1.5 1-4
2014-08-28 00:00:00.000 2.6 1-4
2014-08-28 00:00:00.000 1.5 1-4
2014-08-28 00:00:00.000 3.3 1-4
2014-08-28 00:00:00.000 1.1 1-4
2014-08-28 00:00:00.000 8.5 5-10
2014-08-28 00:00:00.000 8.6 5-10
2014-08-28 00:00:00.000 1.3 1-4
You can use the Create Table ... As Select... syntax
CREATE TABLE temp_table AS
SELECT [date], [length],
CASE
WHEN length BETWEEN 1 AND 4 THEN '1-4'
WHEN length BETWEEN 5 AND 10 THEN '5-10'
WHEN length BETWEEN 11 AND 15 THEN '11-15'
END AS LENGTH_RANGE
FROM orig_table
Sources:
Tech on the Net - SQL: CREATE TABLE AS Statement
MSDN - CREATE TABLE AS SELECT
Oracle - Create Table
...
I understand your question. but your answer already available on following link.
Click here
So refer this link and get more details.
--May help this
;WITH cte (
[Date]
,[Length]
)
AS (
SELECT cast('2014-08-28 00:00:00.000' AS DATETIME)
,CAST('1.5' AS DECIMAL(4, 2))
UNION ALL
SELECT '2014-08-28 00:00:00.000'
,'2.6'
UNION ALL
SELECT '2014-08-28 00:00:00.000'
,'1.5'
UNION ALL
SELECT '2014-08-28 00:00:00.000'
,'3.3'
UNION ALL
SELECT '2014-08-28 00:00:00.000'
,'1.1'
UNION ALL
SELECT '2014-08-28 00:00:00.000'
,'8.5'
UNION ALL
SELECT '2014-08-28 00:00:00.000'
,'8.6'
UNION ALL
SELECT '2014-08-28 00:00:00.000'
,'11.3'
)
SELECT *
,CASE
WHEN Length < 1
THEN '< 1'
WHEN Length BETWEEN 1
AND 4
THEN '1-4'
WHEN Length BETWEEN 5
AND 10
THEN '5-10'
WHEN Length BETWEEN 11
AND 15
THEN '11-15'
WHEN Length > 15
THEN '> 15'
END AS Length_Range
FROM cte
Related
I've been trying to get start and end dates range for each quarter given a specific date/year, like this:
SELECT DATEADD(mm, (quarter - 1) * 3, year_date) StartDate,
DATEADD(dd, 0, DATEADD(mm, quarter * 3, year_date)) EndDate
--quarter QuarterNo
FROM
(
SELECT '2012-01-01' year_date
) s CROSS JOIN
(
SELECT 1 quarter UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4
) q
which produces the following output:
2012-01-01 00:00:00 2012-04-01 00:00:00
2012-04-01 00:00:00 2012-07-01 00:00:00
2012-07-01 00:00:00 2012-10-01 00:00:00
2012-10-01 00:00:00 2013-01-01 00:00:00
Problem: I need to do this for a given start_date and end_date, the problem being the end_date=current_day, so how can I achieve this:
2012-01-01 00:00:00 2012-04-01 00:00:00
2012-04-01 00:00:00 2012-07-01 00:00:00
2012-07-01 00:00:00 2012-10-01 00:00:00
2012-10-01 00:00:00 2013-01-01 00:00:00
... ...
2021-01-01 00:00:00 2021-01-06 00:00:00
I think here is what you want to do :
SET startdatevar AS DATEtime = '2020-01-10'
;WITH RECURSIVE cte AS (
SELECT startdatevar AS startdate , DATEADD(QUARTER, 1 , startdatevar) enddate , 1 quarter
UNION ALL
SELECT enddate , CASE WHEN DATEADD(QUARTER, 1 , enddate) > CURRENT_DATE() THEN GETDATE() ELSE DATEADD(QUARTER, 1 , enddate) END enddate, quarter + 1
FROM cte
WHERE
cte.enddate <= CURRENT_DATE()
and quarter < 4
)
SELECT * FROM cte
to use your code , if you want to have more than 4 quarters :
SET quarter_limit = DATEDIFF(quarter , <startdate>,<enddate>)
;WITH RECURSIVE cte(q, qDate,enddate) as
(
select 1,
DATEFROMPARTS(year('2012-01-01'::date), 1, 1) -- First quarter date
,time_slice('2012-01-01'::date, 3, 'MONTH', 'END')
UNION ALL
select q+1,
DATEADD(q, 1, qdate) -- next quarter start date
,time_slice(qdate::date, (q+1)*3, 'MONTH', 'END')
from cte
where q < quarter_limit -- limiting the number of next quarters
AND cte.endDate <= <enddate>
)
SELECT * FROM cte
After #eshirvana's answer, I came up with this slightly change after your answer:
WITH RECURSIVE cte(q, qDate,enddate) as
(
select 1,
DATEFROMPARTS(year('2012-01-01'::date), 1, 1) -- First quarter date
,time_slice('2012-01-01'::date, 3, 'MONTH', 'END')
UNION ALL
select q+1,
DATEADD(q, 1, qdate) -- next quarter start date
,time_slice(qdate::date, (q+1)*3, 'MONTH', 'END')
from cte
where q <4 -- limiting the number of next quarters
AND cte.endDate <= CURRENT_DATE()
)
SELECT * FROM cte
Which works fine for whatever year I pass there (2012 will produce 4 records, 2021 just one, since we're still on the first quarter right now).
[EDIT]: it still doesn't work as expected after your 2nd code sugestion:
WITH RECURSIVE cte(q, qDate,enddate) as
(
select 1,
DATEFROMPARTS(year('2012-01-01'::date), 1, 1) -- First quarter date
,CASE WHEN time_slice('2012-01-01'::date, 3, 'MONTH', 'END') > CURRENT_DATE
THEN current_date
ELSE time_slice('2012-01-01'::date, 3, 'MONTH', 'END')
END
UNION ALL
select q+1,
DATEADD(q, 1, qdate) -- next quarter start date
,time_slice(qdate::date, (q+1)*3, 'MONTH', 'END')
from cte
where q < DATEDIFF(quarter , '2012-01-01'::date,'2021-01-06'::date)
AND cte.endDate <= '2021-01-06'::date
)
SELECT * FROM cte
is outputing this:
Sorry #eshirvana, it doesn't work as expected though. It all goes well to some point, but it's not returning all the records. Instead, it produces less records and wrong one, like this:
1 2012-01-01 2012-04-01
2 2012-04-01 2012-07-01
3 2012-07-01 2012-10-01
4 2012-10-01 2013-01-01
5 2013-01-01 2013-10-01
6 2013-04-01 2013-07-01
7 2013-07-01 2013-10-01
8 2013-10-01 2014-01-01
9 2014-01-01 2015-01-01
10 2014-04-01 2015-01-01
11 2014-07-01 2016-10-01
12 2014-10-01 2015-01-01
13 2015-01-01 2015-07-01
14 2015-04-01 2015-07-01
15 2015-07-01 2018-10-01
16 2015-10-01 2018-01-01
17 2016-01-01 2016-10-01
18 2016-04-01 2019-07-01
19 2016-07-01 2017-07-01
20 2016-10-01 2020-01-01
21 2017-01-01 2017-04-01
22 2017-04-01 2019-07-01
23 2017-07-01 2021-10-01
Although my logic it's still not ok for not printing just Q1 dates for 2021, could this output issues be related to date format or something?
Now, it seems to be working, at least for 2012-01-01 till today (2021-01-06).
The code :
WITH RECURSIVE cte(q, qDate,enddate) as
(
select
-- it might not be the first quarter, so better to protect that:
quarter('2012-01-01'::date)::numeric
, DATEFROMPARTS(year('2012-01-01'::date), 1, 1) -- First quarter date
, CASE WHEN time_slice('2012-01-01'::date, 3, 'MONTH', 'END') > '2021-01-06'::date
THEN '2021-01-06'::date
ELSE time_slice('2012-01-01'::date, 3, 'MONTH', 'END')
END
UNION ALL
select q+1
, DATEADD(q, 1, qdate) -- next quarter start date
,CASE WHEN time_slice(DATEADD(q, 1, qdate), 3, 'MONTH', 'END')> '2021-01-06'::date
THEN '2021-01-06'::date
ELSE time_slice(DATEADD(q, 1, qdate), 3, 'MONTH', 'END')
END
from cte
where q <= DATEDIFF(quarter , '2012-01-01'::date,'2021-01-06'::date)
AND cte.endDate <= '2021-01-06'::date
)
SELECT * FROM cte
The output:
1 2012-01-01 2012-04-01
2 2012-04-01 2012-07-01
3 2012-07-01 2012-10-01
4 2012-10-01 2013-01-01
5 2013-01-01 2013-04-01
6 2013-04-01 2013-07-01
7 2013-07-01 2013-10-01
8 2013-10-01 2014-01-01
9 2014-01-01 2014-04-01
10 2014-04-01 2014-07-01
11 2014-07-01 2014-10-01
12 2014-10-01 2015-01-01
13 2015-01-01 2015-04-01
14 2015-04-01 2015-07-01
15 2015-07-01 2015-10-01
16 2015-10-01 2016-01-01
17 2016-01-01 2016-04-01
18 2016-04-01 2016-07-01
19 2016-07-01 2016-10-01
20 2016-10-01 2017-01-01
21 2017-01-01 2017-04-01
22 2017-04-01 2017-07-01
23 2017-07-01 2017-10-01
24 2017-10-01 2018-01-01
25 2018-01-01 2018-04-01
26 2018-04-01 2018-07-01
27 2018-07-01 2018-10-01
28 2018-10-01 2019-01-01
29 2019-01-01 2019-04-01
30 2019-04-01 2019-07-01
31 2019-07-01 2019-10-01
32 2019-10-01 2020-01-01
33 2020-01-01 2020-04-01
34 2020-04-01 2020-07-01
35 2020-07-01 2020-10-01
36 2020-10-01 2021-01-01
37 2021-01-01 2021-01-06
In case you're wondering: yes, the idea is to present the end_date as last_day of the month+one. But it could easily be adapted.
It's not pretty, but I think it's somehow easy to understand.
I have a temp table
BusinessDate SSQ_CompScore
2011-01-05 00:00:00.000 41
2011-01-06 00:00:00.000 6
2011-01-07 00:00:00.000 1
2011-01-10 00:00:00.000 8
2011-01-11 00:00:00.000 48
2011-01-12 00:00:00.000 50
2011-01-13 00:00:00.000 59
I need to calculate delta for each current date.
I have prepared a solution but it doesn't work where date as not consecutive.
Can you please help?
select t1.businessdate, t1.ssq_compscore, (t2.ssq_compscore - t1.ssq_compscore) as delta
from #temp t1
left join #temp t2 on t1.businessdate = DATEADD(dd,1,t2.businessdate)
where t1.businessdate >='20180814'
Result set should be as
BusinessDate SSQ_CompScore Delta
2011-01-05 00:00:00.000 41 NULL
2011-01-06 00:00:00.000 6 35
2011-01-07 00:00:00.000 1 5
2011-01-10 00:00:00.000 8 7
2011-01-11 00:00:00.000 48 40
2011-01-12 00:00:00.000 50 2
2011-01-13 00:00:00.000 59 9
Not sure if this is the most efficient way but it works as far as I see
SELECT businessdate, SSQ_CompScore ,
SSQ_CompScore - (SELECT SSQ_CompScore
FROM temp
WHERE businessdate < t1.businessdate
ORDER BY businessdate DESC
LIMIT 1) as delta
FROM temp t1
ORDER BY businessdate ASC
I need to compare 2 dates and return the number of days in between. Here is a table as example:
+----+--------+-------------------------+-------------------------+
| id | userid | datestarted | datefinished |
+----+--------+-------------------------+-------------------------+
| | | | |
| 1 | 23 | 2014-03-25 09:05:00.000 | 2014-03-25 12:15:00.000 |
| 2 | 43 | 2014-03-25 09:05:00.000 | 2014-03-25 12:15:00.000 |
| 3 | 23 | 2014-03-31 09:05:00.000 | 2014-03-31 12:15:00.000 |
| 4 | 12 | 2014-03-25 09:05:00.000 | 2014-03-26 12:15:00.000 |
+----+--------+-------------------------+-------------------------+
In the first 3 cases, we have the same day, only the hours don't match.
Datestarted = 2014-03-25 09:05:00.000
Datefinished = 2014-03-25 12:15:00.000
We only input hours and minutes.
Until now, wee needed only to show the difference as whole number, without decimal points, and did it like this:
DATEDIFF(carsharing.datestarted, carsharing.datefinished)
But now, we have to show the difference between the dates as 0,5 day, if it is less than 4,5 hours. If the difference is greater it should stay as 1 day.
In the more complecated last case from the table, we should also compare and show difference between two different days
Datestarted = 2014-03-25 09:05:00.000
Datefinished = 2014-03-26 12:15:00.000
Here the result should be 1,5 days
I believe this is what you're looking for - this will round the difference to 0.5 for anything under 4.5 hours in the day, and everything else over that will go to a full day:
Declare #StartDate DateTime = '2014-03-25 09:05:00.000',
#EndDate DateTime = '2014-03-26 12:15:00.000'
;With TotalHours As
(
Select DateDiff(Minute, #StartDate, #EndDate) / 60.0 As TotalHours
)
Select Case
When TotalHours % 24 = 0
Then Floor(TotalHours / 24)
When TotalHours % 24 < 4.5
Then Floor(TotalHours / 24) + 0.5
Else Floor(TotalHours / 24) + 1.0
End As Days
From TotalHours
You can try this query. It gets the difference in minutes and multiply it by 2 in order to get a 0.5 day range. It then devide it by 24 hours and by 60 minutes before calculating the Ceiling value. Once you have it, it can be devide by 2 again.
When the value is over 4.5*24*60 (4.5 days in minutes), it only has to be devided by 24 and 60.
Query:
Select id, userid, datestarted, datefinished
, Days = Case When DATEDIFF(minute, datestarted, datefinished) > 4.5*60*24
then DATEDIFF(minute, datestarted, datefinished) / 24 / 60
else CEILING(((2.0*DATEDIFF(minute, datestarted, datefinished)) / 24 / 60)) / 2
end
From #dates
Output:
id userid datestarted datefinished Days
1 23 2014-03-25 09:05:00.000 2014-03-25 12:15:00.000 0.500000
2 43 2014-03-25 09:05:00.000 2014-03-25 12:15:00.000 0.500000
3 23 2014-03-31 09:05:00.000 2014-03-31 12:15:00.000 0.500000
4 12 2014-03-25 09:05:00.000 2014-03-26 12:15:00.000 1.500000
5 12 2014-03-25 09:05:00.000 2014-03-29 12:15:00.000 4.500000
6 12 2014-03-25 09:05:00.000 2014-03-29 22:15:00.000 4.000000
Sample Data
declare #dates table(id int, userid int, datestarted datetime, datefinished datetime);
insert into #dates(id, userid, datestarted, datefinished) values
(1, 23, '2014-03-25 09:05:00.000', '2014-03-25 12:15:00.000')
, (2, 43, '2014-03-25 09:05:00.000', '2014-03-25 12:15:00.000')
, (3, 23, '2014-03-31 09:05:00.000', '2014-03-31 12:15:00.000')
, (4, 12, '2014-03-25 09:05:00.000', '2014-03-26 12:15:00.000')
, (5, 12, '2014-03-25 09:05:00.000', '2014-03-29 12:15:00.000')
, (6, 12, '2014-03-25 09:05:00.000', '2014-03-29 22:15:00.000')
DECLARE
#StartDate datetime = '2014-03-25 09:05:00.000'
,#EndDate datetime = '2014-03-26 09:05:00.000'
;WITH d AS (SELECT DATEDIFF(d,#StartDate,#EndDate) Dys)
,h AS (SELECT DATEDIFF(hh,#StartDate,#EndDate) Hrs)
SELECT d.Dys + CASE WHEN (h.Hrs - d.Dys*24) = 0 THEN 0 ELSE CASE WHEN (h.Hrs - d.Dys*24) < 4.5 THEN 0.5 ELSE 1 END END
FROM d,h
I have two SQL Server tables containing the following information:
Table t_venues:
venue_id is unique
venue_id | start_date | end_date
1 | 01/01/2014 | 02/01/2014
2 | 05/01/2014 | 05/01/2014
3 | 09/01/2014 | 15/01/2014
4 | 20/01/2014 | 30/01/2014
Table t_venueuser:
venue_id is not unique
venue_id | start_date | end_date
1 | 02/01/2014 | 02/01/2014
2 | 05/01/2014 | 05/01/2014
3 | 09/01/2014 | 10/01/2014
4 | 23/01/2014 | 25/01/2014
From these two tables I need to find the dates that haven't been selected for each range, so the output would look like this:
venue_id | start_date | end_date
1 | 01/01/2014 | 01/01/2014
3 | 11/01/2014 | 15/01/2014
4 | 20/01/2014 | 22/01/2014
4 | 26/01/2014 | 30/01/2014
I can compare the two tables and get the date ranges from t_venues to appear in my query using 'except' but I can't get the query to produce the non-selected dates. Any help would be appreciated.
Calendar Table!
Another perfect candidate for a calendar table. If you can't be bothered to search for one, here's one I made earlier.
Setup Data
DECLARE #t_venues table (
venue_id int
, start_date date
, end_date date
);
INSERT INTO #t_venues (venue_id, start_date, end_date)
VALUES (1, '2014-01-01', '2014-01-02')
, (2, '2014-01-05', '2014-01-05')
, (3, '2014-01-09', '2014-01-15')
, (4, '2014-01-20', '2014-01-30')
;
DECLARE #t_venueuser table (
venue_id int
, start_date date
, end_date date
);
INSERT INTO #t_venueuser (venue_id, start_date, end_date)
VALUES (1, '2014-01-02', '2014-01-02')
, (2, '2014-01-05', '2014-01-05')
, (3, '2014-01-09', '2014-01-10')
, (4, '2014-01-23', '2014-01-25')
;
The Query
SELECT t_venues.venue_id
, calendar.the_date
, CASE WHEN t_venueuser.venue_id IS NULL THEN 1 ELSE 0 END As is_available
FROM dbo.calendar /* see: http://gvee.co.uk/files/sql/dbo.numbers%20&%20dbo.calendar.sql for an example */
INNER
JOIN #t_venues As t_venues
ON t_venues.start_date <= calendar.the_date
AND t_venues.end_date >= calendar.the_date
LEFT
JOIN #t_venueuser As t_venueuser
ON t_venueuser.venue_id = t_venues.venue_id
AND t_venueuser.start_date <= calendar.the_date
AND t_venueuser.end_date >= calendar.the_date
ORDER
BY t_venues.venue_id
, calendar.the_date
;
The Result
venue_id the_date is_available
----------- ----------------------- ------------
1 2014-01-01 00:00:00.000 1
1 2014-01-02 00:00:00.000 0
2 2014-01-05 00:00:00.000 0
3 2014-01-09 00:00:00.000 0
3 2014-01-10 00:00:00.000 0
3 2014-01-11 00:00:00.000 1
3 2014-01-12 00:00:00.000 1
3 2014-01-13 00:00:00.000 1
3 2014-01-14 00:00:00.000 1
3 2014-01-15 00:00:00.000 1
4 2014-01-20 00:00:00.000 1
4 2014-01-21 00:00:00.000 1
4 2014-01-22 00:00:00.000 1
4 2014-01-23 00:00:00.000 0
4 2014-01-24 00:00:00.000 0
4 2014-01-25 00:00:00.000 0
4 2014-01-26 00:00:00.000 1
4 2014-01-27 00:00:00.000 1
4 2014-01-28 00:00:00.000 1
4 2014-01-29 00:00:00.000 1
4 2014-01-30 00:00:00.000 1
(21 row(s) affected)
The Explanation
Our calendar tables contains an entry for every date.
We join our t_venues (as an aside, if you have the choice, lose the t_ prefix!) to return every day between our start_date and end_date. Example output for venue_id=4 for just this join:
venue_id the_date
----------- -----------------------
4 2014-01-20 00:00:00.000
4 2014-01-21 00:00:00.000
4 2014-01-22 00:00:00.000
4 2014-01-23 00:00:00.000
4 2014-01-24 00:00:00.000
4 2014-01-25 00:00:00.000
4 2014-01-26 00:00:00.000
4 2014-01-27 00:00:00.000
4 2014-01-28 00:00:00.000
4 2014-01-29 00:00:00.000
4 2014-01-30 00:00:00.000
(11 row(s) affected)
Now we have one row per day, we [outer] join our t_venueuser table. We join this in much the same manner as before, but with one added twist: we need to join based on the venue_id too!
Running this for venue_id=4 gives this result:
venue_id the_date t_venueuser_venue_id
----------- ----------------------- --------------------
4 2014-01-20 00:00:00.000 NULL
4 2014-01-21 00:00:00.000 NULL
4 2014-01-22 00:00:00.000 NULL
4 2014-01-23 00:00:00.000 4
4 2014-01-24 00:00:00.000 4
4 2014-01-25 00:00:00.000 4
4 2014-01-26 00:00:00.000 NULL
4 2014-01-27 00:00:00.000 NULL
4 2014-01-28 00:00:00.000 NULL
4 2014-01-29 00:00:00.000 NULL
4 2014-01-30 00:00:00.000 NULL
(11 row(s) affected)
See how we have a NULL value for rows where there is no t_venueuser record. Genius, no? ;-)
So in my first query I gave you a quick CASE statement that shows availability (1=available, 0=not available). This is for illustration only, but could be useful to you.
You can then either wrap the query up and then apply an extra filter on this calculated column or simply add a where clause in: WHERE t_venueuser.venue_id IS NULL and that will do the same trick.
This is a complete hack, but it gives the results you require, I've only tested it on the data you provided so there may well be gotchas with larger sets.
In general what you are looking at solving here is a variation of gaps and islands problem ,this is (briefly) a sequence where some items are missing. The missing items are referred as gaps and the existing items are referred as islands. If you would like to understand this issue in general check a few of the articles:
Simple talk article
blogs.MSDN article
SO answers tagged gaps-and-islands
Code:
;with dates as
(
SELECT vdates.venue_id,
vdates.vdate
FROM ( SELECT DATEADD(d,sv.number,v.start_date) vdate
, v.venue_id
FROM t_venues v
INNER JOIN master..spt_values sv
ON sv.type='P'
AND sv.number BETWEEN 0 AND datediff(d, v.start_date, v.end_date)) vdates
LEFT JOIN t_venueuser vu
ON vdates.vdate >= vu.start_date
AND vdates.vdate <= vu.end_date
AND vdates.venue_id = vu.venue_id
WHERE ISNULL(vu.venue_id,-1) = -1
)
SELECT venue_id, ISNULL([1],[2]) StartDate, [2] EndDate
FROM (SELECT venue_id, rDate, ROW_NUMBER() OVER (PARTITION BY venue_id, DateType ORDER BY rDate) AS rType, DateType as dType
FROM( SELECT d1.venue_id
,d1.vdate AS rDate
,'1' AS DateType
FROM dates AS d1
LEFT JOIN dates AS d0
ON DATEADD(d,-1,d1.vdate) = d0.vdate
LEFT JOIN dates AS d2
ON DATEADD(d,1,d1.vdate) = d2.vdate
WHERE CASE ISNULL(d2.vdate, '01 Jan 1753') WHEN '01 Jan 1753' THEN '2' ELSE '1' END = 1
AND ISNULL(d0.vdate, '01 Jan 1753') = '01 Jan 1753'
UNION
SELECT d1.venue_id
,ISNULL(d2.vdate,d1.vdate)
,'2'
FROM dates AS d1
LEFT JOIN dates AS d2
ON DATEADD(d,1,d1.vdate) = d2.vdate
WHERE CASE ISNULL(d2.vdate, '01 Jan 1753') WHEN '01 Jan 1753' THEN '2' ELSE '1' END = 2
) res
) src
PIVOT (MIN (rDate)
FOR dType IN
( [1], [2] )
) AS pvt
Results:
venue_id StartDate EndDate
1 2014-01-01 2014-01-01
3 2014-01-11 2014-01-15
4 2014-01-20 2014-01-22
4 2014-01-26 2014-01-30
I have a query that groups aggregated sum values by month.
This is the query:
Declare #IsByStatus bit
Set #IsByStatus = 0
SELECT
CAST((DATEDIFF(month, '2012-01-01T06:00:00', datTimeStamp)) AS int) AS [Index] ,
Min(datTimeStamp) as [From],
Max(datTimeStamp) as [To],
Sum(CASE CAST(intIO_ID AS nvarchar(100))
WHEN N'284' THEN Value ELSE NULL END) AS [286]
FROM
[IOValuesFn](#IsByStatus) IOValues
WHERE
datTimeStamp >= '2012-01-01T06:00:00'
AND datTimeStamp < '2013-01-01T05:59:59'
AND intIO_ID IN (284)
GROUP BY
CAST ((DATEDIFF(Month,'2012-01-01T06:00:00', datTimeStamp)) AS int)
ORDER BY
[From]
And this is the result:
Index From To 286
0 2012-01-07 07:00:00.000 2012-01-31 23:00:00.000 142579.898864746
1 2012-02-01 00:00:00.000 2012-02-29 23:00:00.000 139486.498001099
2 2012-03-01 00:00:00.000 2012-03-31 23:00:00.000 99516.3022232056
3 2012-04-01 00:00:00.000 2012-04-30 23:00:00.000 84597.599899292
4 2012-05-01 00:00:00.000 2012-05-31 23:00:00.000 67085.2983112335
5 2012-06-01 00:00:00.000 2012-06-30 23:00:00.000 67768.9982643127
6 2012-07-01 00:00:00.000 2012-07-31 23:00:00.000 121100.264842987
7 2012-08-01 00:00:00.000 2012-08-31 23:00:00.000 165768.90776825
8 2012-09-01 00:00:00.000 2012-09-30 23:00:00.000 97441.7333068848
9 2012-10-01 00:00:00.000 2012-10-31 23:00:00.000 153764.736312866
10 2012-11-01 00:00:00.000 2012-11-30 23:00:00.000 153601.413961411
11 2012-12-01 00:00:00.000 2012-12-31 23:00:00.000 142521.07028389
12 2013-01-01 00:00:00.000 2013-01-01 05:00:00.000 1192.32000732422
Now I want to do the similar logic, that will also insert an offset in the month start-end time.
e.g. the first period will start on january 1'st on 11:00 AM and will end at february 1 10:59:59 AM.
Same goes for each subsequent month.
Thanks in advance for your help, Omer
Have a look at the example below. The trick is to add the negative amount of offset such that any hour prior to 11am on the first day of the month is "pushed" into the prior month.
Schema Setup:
create function iovaluesfn(#isbystatus bit) returns table as return
select datTimeStamp = '20130101 10:50', intIO_ID = 284, Value = 1 union all
select '20130101 11:00', 284, 1 union all
select '20130102 11:00', 284, 2 union all
select '20130301 11:00', 284, 3 union all
select '20130401 11:00', 284, 4 union all
select '20120501 11:00', 284, 5 union all
select '20120601 11:00', 284, 6 union all
select '20120101 11:00', 284, 7 union all
select '20120102 11:00', 284, 8 union all
select '20120101 11:01', 284, 9 union all
select '20120101 10:59', 284,10 union all -- ** this value is counted in Dec 2011
select '20120101 11:00', 284,11 union all
select '20120101 11:01', 281,12 union all
select '20120101 10:59', 281,13 union all
select '20120101 11:00', 281,14
GO
Query:
Declare #IsByStatus bit;
Set #IsByStatus = 0;
;with IOValues as (
select DATEADD(hour, -11, datTimeStamp) datTimeStamp, intIO_ID, Value
FROM [IOValuesFn](#IsByStatus)
WHERE datTimeStamp >= '2012-01-01T06:00:00' AND datTimeStamp < '2013-01-01T05:59:59'
AND intIO_ID IN (284)
)
SELECT CAST((DATEDIFF(month,'2012-01-01T06:00:00',datTimeStamp)) AS int) AS [Index],
Min(datTimeStamp) as [From],
Max(datTimeStamp) as [To],
Sum(CASE CAST(intIO_ID AS nvarchar(100))
WHEN N'284' THEN Value ELSE NULL END) AS [286]
FROM IOValues
GROUP BY CAST ((DATEDIFF(Month,'2012-01-01T06:00:00',datTimeStamp))AS int)
order by [From];
Results:
| INDEX | FROM | TO | 286 |
----------------------------------------------------------
| -1 | December, 31 2011 | December, 31 2011 | 10*** |
| 0 | January, 01 2012 | January, 02 2012 | 35 |
| 4 | May, 01 2012 | May, 01 2012 | 5 |
| 5 | June, 01 2012 | June, 01 2012 | 6 |
SQL Fiddle Demo