Indexing Time in Redshift - sql

i have a dataset with that has sales by month and a column for when an promotion happens for a number of products.
i want to index the months so that i can compare the different products over a pre and post 12m period easily
this is the data i have
Date
sales.
Promo?
Jan 21
100
Feb 21
110.
Mar 21
100.
apr 21
110.
may 21
90.
jun 21
100.
jul 21
120.
aug 21
140.
X
sep 21
100.
oct 21
90.
nov 21
100.
dec 21
120.
jan 22
110.
feb 22
100
this is what i want
can someone tell me how to do this in redshift?
Date
sales.
Promo?
month index
Jan 21
100
-7.
Feb 21
110.
-6
Mar 21
100.
-5
apr 21
110.
-4
may 21
90.
-3
jun 21
100.
-2
jul 21
120.
-1
aug 21
140.
X
0
sep 21
100.
1
oct 21
90.
2
nov 21
100.
3
dec 21
120.
4
jan 22
110.
5
feb 22
100
6

Related

Generate One year dates using Oracle SQL

I have a table with three ID and Dates
i want generate dates of one year from current date and before and after six months
Then i want to plot three dates on this one year generated calandar
I tried
SELECT (TO_DATE(SYSDATE)-180) + ROWNUM DT
FROM (SELECT 1
FROM DUAL
CONNECT BY LEVEL <=180)
The concept of "month" is variable, so you may want to double check if "6 months" is really what you're looking for. It can give unexpected results if you don't know the oddities of date math.
That being said, a calendar which contains 6 months on either side of the current date can be generated with the following. Note that 184 days is the longest a 6 month span can last (July-December).
SELECT dt
FROM (SELECT TRUNC(SYSDATE - 184) + LEVEL AS dt
FROM dual
CONNECT BY LEVEL <= 369)
WHERE dt BETWEEN add_months(TRUNC(SYSDATE), -6) AND add_months(TRUNC(SYSDATE), 6);
Literally following what you said: there's a table with 3 IDs and their dates, and you want to plot the calendar.
Using a hierarchical query, dates are generated as
SQL> with
2 threeid (id, datum) as
3 (select 1, date '2020-05-29' from dual union all
4 select 2, date '2020-01-01' from dual union all
5 select 3, date '2020-02-29' from dual
6 ),
7 cal as
8 (select add_months(datum, -6) + column_value - 1 datum
9 from threeid cross join
10 table(cast(multiset(select level from dual
11 connect by level <= add_months(datum, 6) - add_months(datum, -6)
12 ) as sys.odcinumberlist))
13 where id = 1 --> for the 1st ID; change that for other calendars
14 )
15 select * from cal order by datum;
DATUM
----------
29.11.2019
30.11.2019
01.12.2019
02.12.2019
03.12.2019
<snip>
25.11.2020
26.11.2020
27.11.2020
28.11.2020
366 rows selected.
If you want to plot that, instead of line #15 you'd use this ...
<snip>
15 select lpad(month, 20, ' ') month,
16 "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
17 from (select to_char(dt, 'fmMonthfm YYYY') month,
18 week,
19 max(decode(to_char(dt, 'd'), '1', lpad(to_char(dt, 'fmdd'), 2))) "Mon",
20 max(decode(to_char(dt, 'd'), '2', lpad(to_char(dt, 'fmdd'), 2))) "Tue",
21 max(decode(to_char(dt, 'd'), '3', lpad(to_char(dt, 'fmdd'), 2))) "Wed",
22 max(decode(to_char(dt, 'd'), '4', lpad(to_char(dt, 'fmdd'), 2))) "Thu",
23 max(decode(to_char(dt, 'd'), '5', lpad(to_char(dt, 'fmdd'), 2))) "Fri",
24 max(decode(to_char(dt, 'd'), '6', lpad(to_char(dt, 'fmdd'), 2))) "Sat",
25 max(decode(to_char(dt, 'd'), '7', lpad(to_char(dt, 'fmdd'), 2))) "Sun"
26 from ( select dt,
27 case when dt >= to_date(to_char(dt, 'dd/') ||'12/'||
28 to_char(sysdate,'yyyy'), 'dd/mm/yyyy')
29 and wk = '01'
30 then '53'
31 else wk
32 end week
33 from (select datum dt, to_char(datum, 'iw') wk
34 from cal
35 )
36 )
37 group by to_char(dt, 'fmMonthfm YYYY'), week
38 )
39 order by to_date( month, 'Month YYYY' ), to_number(week);
... and get that:
MONTH Mon Tue Wed Thu Fri Sat Sun
-------------------- -------- -------- -------- -------- -------- -------- --------
November 2019 29 30
December 2019 30 31
December 2019 1
December 2019 2 3 4 5 6 7 8
December 2019 9 10 11 12 13 14 15
December 2019 16 17 18 19 20 21 22
December 2019 23 24 25 26 27 28 29
January 2020 1 2 3 4 5
January 2020 6 7 8 9 10 11 12
January 2020 13 14 15 16 17 18 19
January 2020 20 21 22 23 24 25 26
January 2020 27 28 29 30 31
February 2020 1 2
February 2020 3 4 5 6 7 8 9
February 2020 10 11 12 13 14 15 16
February 2020 17 18 19 20 21 22 23
February 2020 24 25 26 27 28 29
March 2020 1
March 2020 2 3 4 5 6 7 8
March 2020 9 10 11 12 13 14 15
March 2020 16 17 18 19 20 21 22
March 2020 23 24 25 26 27 28 29
March 2020 30 31
April 2020 1 2 3 4 5
April 2020 6 7 8 9 10 11 12
April 2020 13 14 15 16 17 18 19
April 2020 20 21 22 23 24 25 26
April 2020 27 28 29 30
May 2020 1 2 3
May 2020 4 5 6 7 8 9 10
May 2020 11 12 13 14 15 16 17
May 2020 18 19 20 21 22 23 24
May 2020 25 26 27 28 29 30 31
June 2020 1 2 3 4 5 6 7
June 2020 8 9 10 11 12 13 14
June 2020 15 16 17 18 19 20 21
June 2020 22 23 24 25 26 27 28
June 2020 29 30
July 2020 1 2 3 4 5
July 2020 6 7 8 9 10 11 12
July 2020 13 14 15 16 17 18 19
July 2020 20 21 22 23 24 25 26
July 2020 27 28 29 30 31
August 2020 1 2
August 2020 3 4 5 6 7 8 9
August 2020 10 11 12 13 14 15 16
August 2020 17 18 19 20 21 22 23
August 2020 24 25 26 27 28 29 30
August 2020 31
September 2020 1 2 3 4 5 6
September 2020 7 8 9 10 11 12 13
September 2020 14 15 16 17 18 19 20
September 2020 21 22 23 24 25 26 27
September 2020 28 29 30
October 2020 1 2 3 4
October 2020 5 6 7 8 9 10 11
October 2020 12 13 14 15 16 17 18
October 2020 19 20 21 22 23 24 25
October 2020 26 27 28 29 30 31
November 2020 1
November 2020 2 3 4 5 6 7 8
November 2020 9 10 11 12 13 14 15
November 2020 16 17 18 19 20 21 22
November 2020 23 24 25 26 27 28
64 rows selected.
SQL>
(That nice calendar query is originally (at least, I think so) posted on OraFAQ site; I adjusted it, hoping that it correctly displays dates)

Add a day to a predefined date SQL Server 2008 R2

My question is very simple, I am making a query which I intend to make an insertion from two dates to a temp Table.
That is, 2020-04-01 00:00:00 and 20-04-01 23:59:00, hence the number of days you need increases.
I am doing it this way E.G:
DECLARE #StartDate DATETIME = '2020-04-01'
DECLARE #EndDate DATETIME = '2020-04-01'
SET #StartDate = #StartDate + '00:00:00'
SET #EndDate = #EndDate + '23:59:00'
WHILE (#StartDate <= #EndDate)
BEGIN
--Insert into a temp table
set #StartDate = DATEADD(DAY, 1, #StartDate);
set #EndDate = DATEADD(day, 1, #EndDate);
print #StartDate
print #EndDate
END;
, however it goes into a repetitive cycle and does not stop. Besides, it is not only respecting the increment of the day that I need.
Can someone help me with this please.
I want to get to this:
Initial date: 2020-04-01 00:00:00.
End Date: 2020-04-01 23:59:00.
Starting day increment 2020-04-02 00:00:00
End Date Increment: 2020-04-02 23:59:00.
My query is throwing this at me:
Apr 2 2020 12:00AM
Apr 2 2020 11:59PM
Apr 3 2020 12:00AM
Apr 3 2020 11:59PM
Apr 4 2020 12:00AM
Apr 4 2020 11:59PM
Apr 5 2020 12:00AM
Apr 5 2020 11:59PM
Apr 6 2020 12:00AM
Apr 6 2020 11:59PM
Apr 7 2020 12:00AM
Apr 7 2020 11:59PM
Apr 8 2020 12:00AM
Apr 8 2020 11:59PM
Apr 9 2020 12:00AM
Apr 9 2020 11:59PM
Apr 10 2020 12:00AM
Apr 10 2020 11:59PM
Apr 11 2020 12:00AM
Apr 11 2020 11:59PM
Apr 12 2020 12:00AM
Apr 12 2020 11:59PM
Apr 13 2020 12:00AM
Apr 13 2020 11:59PM
Apr 14 2020 12:00AM
Apr 14 2020 11:59PM
Apr 15 2020 12:00AM
Apr 15 2020 11:59PM
Apr 16 2020 12:00AM
Apr 16 2020 11:59PM
Apr 17 2020 12:00AM
Apr 17 2020 11:59PM
Apr 18 2020 12:00AM
Apr 18 2020 11:59PM
Apr 19 2020 12:00AM
Apr 19 2020 11:59PM
Apr 20 2020 12:00AM
Apr 20 2020 11:59PM
Apr 21 2020 12:00AM
Apr 21 2020 11:59PM
Apr 22 2020 12:00AM
Apr 22 2020 11:59PM
Apr 23 2020 12:00AM
Apr 23 2020 11:59PM
Apr 24 2020 12:00AM
Apr 24 2020 11:59PM
Apr 25 2020 12:00AM
Apr 25 2020 11:59PM
Apr 26 2020 12:00AM
Apr 26 2020 11:59PM
Apr 27 2020 12:00AM
Apr 27 2020 11:59PM
Apr 28 2020 12:00AM
Apr 28 2020 11:59PM
Apr 29 2020 12:00AM
Apr 29 2020 11:59PM
Apr 30 2020 12:00AM
Apr 30 2020 11:59PM
May 1 2020 12:00AM
May 1 2020 11:59PM
May 2 2020 12:00AM
May 2 2020 11:59PM
May 3 2020 12:00AM
May 3 2020 11:59PM
May 4 2020 12:00AM
May 4 2020 11:59PM
May 5 2020 12:00AM
May 5 2020 11:59PM
May 6 2020 12:00AM
May 6 2020 11:59PM
May 7 2020 12:00AM
May 7 2020 11:59PM
May 8 2020 12:00AM
May 8 2020 11:59PM
May 9 2020 12:00AM
May 9 2020 11:59PM
May 10 2020 12:00AM
May 10 2020 11:59PM
May 11 2020 12:00AM
May 11 2020 11:59PM
May 12 2020 12:00AM
May 12 2020 11:59PM
May 13 2020 12:00AM
May 13 2020 11:59PM
May 14 2020 12:00AM
May 14 2020 11:59PM
May 15 2020 12:00AM
May 15 2020 11:59PM
May 16 2020 12:00AM
May 16 2020 11:59PM
May 17 2020 12:00AM
May 17 2020 11:59PM
May 18 2020 12:00AM
May 18 2020 11:59PM
May 19 2020 12:00AM
May 19 2020 11:59PM
May 20 2020 12:00AM
May 20 2020 11:59PM
May 21 2020 12:00AM
May 21 2020 11:59PM
May 22 2020 12:00AM
May 22 2020 11:59PM
May 23 2020 12:00AM
May 23 2020 11:59PM
May 24 2020 12:00AM
May 24 2020 11:59PM
May 25 2020 12:00AM
May 25 2020 11:59PM
May 26 2020 12:00AM
May 26 2020 11:59PM
May 27 2020 12:00AM
May 27 2020 11:59PM
May 28 2020 12:00AM
May 28 2020 11:59PM
May 29 2020 12:00AM
May 29 2020 11:59PM
May 30 2020 12:00AM
May 30 2020 11:59PM
May 31 2020 12:00AM
May 31 2020 11:59PM
Jun 1 2020 12:00AM
Jun 1 2020 11:59PM
Jun 2 2020 12:00AM
Jun 2 2020 11:59PM
Jun 3 2020 12:00AM
Jun 3 2020 11:59PM
Jun 4 2020 12:00AM
Jun 4 2020 11:59PM
Jun 5 2020 12:00AM
Jun 5 2020 11:59PM
Jun 6 2020 12:00AM
Jun 6 2020 11:59PM
Jun 7 2020 12:00AM
Any suggestion?
Where is my mistake ?.
Thank you.
Use a recursive CTE:
DECLARE #StartDate DATETIME = '2020-04-01';
DECLARE #EndDate DATETIME = '2020-04-01';
with dates as (
select #startdate as startdate, dateadd(minute, -1, dateadd(day, 1, #startdate)) as enddate
union all
select dateadd(day, 1, startdate), dateadd(day, 1, enddate)
from dates
where startdate < #enddate
)
select *
from dates
option (maxrecursion 0);
Here is a db<>fiddle.

How to get the data in decline pattern/trending using Oracle SQL?

How can I get the result only for those monthly data in decline pattern/trending ?
And the data as below;
ID JAN FEB MAR APR MAY JUN
112 50 45 40 35 30 20
113 30 30 30 30 30 30
114 20 25 20 20 20 20
115 45 50 60 60 30 30
Expected output ;
ID JAN FEB MAR APR MAY JUN
112 50 45 40 35 30 20
115 45 50 60 60 30 30
Thanks !
SELECT *
FROM your_table
WHERE JAN > JUN
or
SELECT *
FROM your_table
WHERE JAN > FEB
AND FEB > MAR
AND MAR > APR
AND APR > MAY
AND MAY > JUN
It appears that what you're looking for is
SELECT *
FROM SOME_TABLE
WHERE JAN > FEB OR
FEB > MAR OR
MAR > APR OR
APR > MAY OR
MAY > JUN
Best of luck.

T-SQL - Rolling 12 Month Average

I would like to return rolling 12 month averages for each month in a resulting dataset but am not sure how I can do this.
I thought the following script would work:
DECLARE #StartDate as datetime
DECLARE #EndDate as datetime
SET #StartDate = '01/04/2011'
SET #EndDate = getdate()
select x.FinYear, x.FinMonth, x.MonthText, avg(TimeSeconds) [AverageTimeSeconds]
from times x
where (x.TimeOfCall >= #StartDate and x.TimeOfCall < #EndDate)
group by x.FinYear, x.FinMonth, x.MonthText
order by x.FinYear, x.FinMonth
but it only returns the monthly averages, how do I get the 12 month average leading up to each of the months between the start and end date.
The resulting dataset I am looking for is as follows:
Fin Year Fin Month Month Text Avg Time Seconds R12M Avg Seconds
2015/16 01 Apr 100 101
2015/16 02 May 95 98
2015/16 03 Jun 103 100
2015/16 04 Jul 110 100
2015/16 05 Aug 100 100
2015/16 06 Sep 90 97
2015/16 07 Oct 93 97
2015/16 08 Nov 98 100
2015/16 09 Dec 80 98
2015/16 10 Jan 88 98
2015/16 11 Feb 100 98
2016/17 12 Mar 115 100
2016/17 01 Apr 105 100
2016/17 02 May 98 100
2016/17 03 Jun 95 98
2016/17 04 Jul 102 98
2016/17 05 Aug 109 99
2016/17 06 Sep 104 100
2016/17 07 Oct 98 98
2016/17 08 Nov 99 97
2016/17 09 Dec 90 97
the rolling 12 month average is not an average of the monthly averages but an average of the 12 months leading up to the month in question. So January 2017 would be the average of 01 February 2016 - 31 January 2017 and October 2016 would be 01 November 2015 to 31 October 2016.
I hope you can help :-) .
If you have data for every month, then the following calculates the average over the preceding 12 months (note this is the overall average, not the average of the monthly averages):
select x.FinYear, x.FinMonth, x.MonthText, avg(TimeSeconds)as [AverageTimeSeconds],
(sum(sum(TimeSeconds)) over (order by x.FinYear, x.FinMonth rows between 11 preceding and current row) /
sum(count(*)) over (order by x.FinYear, x.FinMonth rows between 11 preceding and current row)
) as avg_12month
from times x
where x.TimeOfCall >= #StartDate and x.TimeOfCall < #EndDate
group by x.FinYear, x.FinMonth, x.MonthText
order by x.FinYear, x.FinMonth;
Note: The where clause affects the 12-month look-back period. In other worse, the look-back will not include months before this period.

Transpose In SQL SERVER

Could you help me one case, below
After Tranpose the table i get result as like this:
Lno OID ConnectedDate
100000224 34931 Feb 7 201,Feb 7 201,Feb 8 201,Feb 8 201,Feb 4 201
100001489 9156 Jun 23 201,Jun 24 201,Jun 25 201,Jun 25 201,Oct 29 201,Oct 29 201
100002153 31514 Oct 5 201
100002740 32367 Sep 14 201,Sep 14 201,Oct 21 201,Sep 15 201,Sep 15 201,Sep 16 201
100004774 31558 May 19 201,May 19 201,May 20 201,May 20 201,Jun 2 201
100004935 5857 Sep 1 201,Sep 1 201,Sep 3 201,Sep 3 201,Sep 29 201,Aug 31 201,Sep 22 201
100004935 31684 Jun 16 201,Jun 17 201,Jun 17 201,Jun 19 201
100004983 33942 Dec 30 201,Dec 30 201,Dec 27 201,Dec 29 201,Dec 28 201
100005055 32347 Sep 14 201,Sep 13 201,Sep 13 201,Oct 1 201,Oct 5 201,Oct 20 201,Nov 17 201,Sep 15 201,Sep 16 201,Dec 4 201
100006146 31481 Apr 30 201,Apr 30 201,May 3 201,May 4 201,May 4 201,Jun 3 201,Jun 4 201,Jun 5 201,Jun 7 201,Jun 12 201
But i want output like this:
LID OID ConnectedDate1 ConnectedDate2 ConnectedDate3 ConnectedDate4
100000224 34931 Feb 7 201 Feb 7 201 Feb 8 201 Feb 8 201
100001489 9156 Jun 23 201 Jun 24 201 Jun 25 201 Jun 25 201
100002153 31514 Oct 5 201
100002740 32367 Sep 14 201 Sep 14 201 Oct 21 201 Sep 15 201
100004774 31558 May 19 201 May 19 201 May 20 201
Plz help me
Thanks in advance
You need the PIVOT command. To give more details, you'd need to provide your query