How to use CASE together with date INTERVAL? - sql

I want to have this query:
SELECT DATE(DATE_SUB(DATE('2010-09-10'), (CASE DATETYPE WHEN 'H' THEN INTERVAL 1 WEEK ELSE INTERVAL 1 YEAR END CASE))) AS wdt
MySQL says it's invalid
also I have tried
SELECT _DATE AS wdt
UNION ALL
CASE DATETYPE
WHEN 'H' THEN SELECT DATE(DATE_SUB(_DATE, INTERVAL 1 YEAR)) AS wdt ;
ELSE SELECT DATE(DATE_SUB(DATE('2010-09-10'), INTERVAL 1 WEEK )) AS wdt;
END CASE;
UNION ALL
SELECT DATE(DATE_SUB(_DATE, INTERVAL 2 WEEK)) AS wdt
which doesn't work also, error in query syntax.
How can I select interval 1 year for dates that are Holidays.

Using two DATE_SUB operations would work:
SELECT IF (DATETYPE = 'H',
DATE_SUB(DATE('2010-09-10'), INTERVAL 1 WEEK),
DATE_SUB(DATE('2010-09-10'), INTERVAL 1 YEAR))
as wdt;

Related

how can I get date in presto sql

I have a code below but it throws an error.
How do I get the date 12 weeks from 2018-01-01 and use the case statement?
select
case when
date between cast('2018-01-01' as date) and DATE_ADD('week',12,cast('2018-01-01' as date)) -interval '1' day
then 'in 12 weeks' as period
from aaa limit 1
Your case statement misses closing end:
WITH dataset AS (
SELECT * FROM (VALUES
(DATE '2018-01-03'),
(DATE '2018-04-04')
) AS t (date))
SELECT
CASE
WHEN date BETWEEN Cast('2018-01-01' AS date) AND date_add('week', 12, cast('2018-01-01' AS date)) - INTERVAL '1' day
THEN 'in 12 weeks'
END AS period
FROM
dataset
LIMIT
1

create table with dates - sql

I have a query that can create a table with dates like below:
with digit as (
select 0 as d union all
select 1 union all select 2 union all select 3 union all
select 4 union all select 5 union all select 6 union all
select 7 union all select 8 union all select 9
),
seq as (
select a.d + (10 * b.d) + (100 * c.d) + (1000 * d.d) as num
from digit a
cross join
digit b
cross join
digit c
cross join
digit d
order by 1
)
select (last_day(sysdate)::date - seq.num)::date as "Date"
from seq;
How could this be changed to generate only dates
Thanks
demo:db<>fiddle
WITH dates AS (
SELECT
date_trunc('month', CURRENT_DATE) AS first_day_of_month,
date_trunc('month', CURRENT_DATE) + interval '1 month -1 day' AS last_day_of_month
)
SELECT
generate_series(first_day_of_month, last_day_of_month, interval '1 day')::date
FROM dates
date_trunc() truncates a type date (or timestamp) to a certain date part. date_trunc('month', ...) removes all parts but year and month. All other parts are set to their lowest possible values. So, the day part is set to 1. That's why you get the first day of month with this.
adding a month returns the first of the next month, subtracting a day from this results in the last day of the current month.
Finally you can generate a date series with start and end date using the generate_series() function
Edit: Redshift does not support generate_series() with type date and timestamp but with integer. So, we need to create an integer series instead and adding the results to the first of the month:
db<>fiddle
WITH dates AS (
SELECT
date_trunc('month', CURRENT_DATE) AS first_day_of_month,
date_trunc('month', CURRENT_DATE) + interval '1 month -1 day' AS last_day_of_month
)
SELECT
first_day_of_month::date + gs
FROM
dates,
generate_series(
date_part('day', first_day_of_month)::int - 1,
date_part('day', last_day_of_month)::int - 1
) as gs
This answers the original version of the question.
You would use generate_series():
select gs.dte
from generate_series(date_trunc('month', now()::date),
date_trunc('month', now()::date) + interval '1 month' - interval '1 day',
interval '1 day'
) gs(dte);
Here is a db<>fiddle.

Oracle SQL - How to retrieve the ID Count difference between today vs yesterday

I have a table that captures when a customer purchases a product. It captures a unique purchase id along with a timestamp of when the purchase was made.
I want to be able to query, the difference between how many purchases were taken today vs yesterday?
Not sure how to query this on oracle?
You can use conditional aggregation:
select sum(case when trunc(datecol) = trunc(sysdate - 1) then 1 else 0 end) as num_yesterday,
sum(case when trunc(datecol) = trunc(sysdate) then 1 else 0 end) as num_today,
sum(case when trunc(datecol) = trunc(sysdate) then 1
when trunc(datecol) = trunc(sysdate - 1) then -1
end) as diff
from t
where datecol >= trunc(sysdate - 1);
you can use the Group function to grouping the purchase day with timestamp information and count the purchase id.
select trunc(purchase_ts) Day, count(purchase_id) Count
from purchase
group by trunc(purchase_ts)
order by 1
Using TRUNC on the column will prevent Oracle from using an index on that column (instead you would need a separate function-based index); instead use a CASE statement to test whether the date is between the start of the day and the start of the next day and then COUNT the values between those ranges:
SELECT COUNT(
CASE
WHEN TRUNC( SYSDATE ) - INTERVAL '1' DAY <= your_date_column
AND your_date_coumn < TRUNC( SYSDATE )
THEN 1
END
) AS count_for_yesterday,
COUNT(
CASE
WHEN TRUNC( SYSDATE ) <= your_date_column
AND your_date_coumn < TRUNC( SYSDATE ) + INTERVAL '1' DAY
THEN 1
END
) AS count_for_today
FROM your_table
WHERE TRUNC( SYSDATE ) - INTERVAL '1' DAY <= your_date_column
AND your_date_coumn < TRUNC( SYSDATE ) + INTERVAL '1' DAY

data of last 4 quarter

I want to fetch data of last 4 quarter including current quarter.
Suppose if I run the query on 30-MAR-2019 then I want data from 01-APR-2018 to 31-MAR-2019
and if I run the query on 01-apr-2019 then I want data between 01-JUL-2018 and 30-JUN-2019
Could you please help me on the same
The tricky part is getting the last day of the quarter.
This solution calculates the starting day of the range by subtracting 9 months from the target date and then truncating with the 'Q' mask which gives us the first day of the quarter. We then calculate that date again, subtract one day then add twelve months and that gives the last day of the current quarter:
with tgt as ( select date '2019-03-30' as dt from dual
union all select date '2019-02-28' as dt from dual
union all select date '2019-04-01' as dt from dual
)
select trunc(tgt.dt - interval '9' month, 'Q') as range_st,
(trunc(tgt.dt - interval '9' month, 'Q') - 1) + interval '12' month as range_end
from tgt
/
There may be a slicker solution out there, but this is the end of my coffee break :)
this will work:
select TRUNC(sysdate+1, 'Q') - interval '9' month,TRUNC(sysdate+1, 'Q') +
interval '3' month -1
from dual ;
01-JUL-2018 30-JUN-2019
select TRUNC(to_date('30-MAR-2019')+1, 'Q') - interval '9'
month,TRUNC(to_date('30-MAR-2019')+1, 'Q') + interval '3' month -1
from dual ;
01-APR-2018 31-MAR-2019
This is dynamically:
With param as (
Select
to_date(extract(year from add_months(sysdate,-12)) ||
lpad((floor(extract(month from add_months(sysdate,-12))/3)*3)+1,2, '0') || '01',
'yyyymmdd') first_date
from dual
)
Select
level quartal,
Add_months(first_date, ((level-1)*3)) from_dat,
Last_day(add_months(first_date, ((level-1)*3)+3)-1) to_dat
From param
connect by level <= 4;
You can do:
select (trunc(sysdate, 'Q') + interval '3' month) as next_quarter_start,
(trunc(sysdate, 'Q') + interval '15' month) - interval '1' day as next_quarter_end
from dual;

Search for holiday doy IN (string) (Postgresql)

This work:
WITH month AS (
SELECT date_part('doy',d.dt) as doy,
dt::date as date
FROM generate_series('2017-01-01','2017-01-15', interval '1 day') as d(dt)
)
SELECT date,
CASE
WHEN doy IN (1,2,3) THEN 0 ELSE 8 END
FROM month
http://sqlfiddle.com/#!15/aed15/10
But if I store 1,2,3 as a string
CREATE TABLE holidays
(id int4,days character(60));
INSERT INTO holidays
(id,days)
VALUES
('2017','1,2,3');
...and replace 1,2,3 with this string:
WITH month AS (
SELECT date_part('doy',d.dt) as doy,
dt::date as date
FROM generate_series('2017-01-01','2017-01-15', interval '1 day') as d(dt)
)
SELECT date, days,
CASE
WHEN doy::text IN (days) THEN 0 ELSE 8 END
FROM month
LEFT JOIN holidays ON id=2017
http://sqlfiddle.com/#!15/aed15/13
It seems that 'days' is not casted correct. But I cannot figure out how.
TIA,
the shortest solution here would be turning string list to array and using ANY construct:
WITH month AS (
SELECT date_part('doy',d.dt) as doy,
dt::date as date
FROM generate_series('2017-01-01','2017-01-15', interval '1 day') as d(dt)
)
SELECT date, days,
CASE
WHEN doy::text = ANY(concat('{',days,'}')::text[]) THEN 0 ELSE 8 END
FROM month
LEFT JOIN holidays ON id=2017
But I would rethink the whole solution, as it feels wrong