How to exclude between a particular date range each year in SQL - sql

I'm trying to exclude the Christmas period between two dates every year in my database. This is the query I'm trying to run. From my understanding this should include every row, for every year with the exception of rows where the month is <= 12 and day <= 15 and where the month is <= 12 and day >= 26.
The result, however, doesn't appear to return any rows at all!
SELECT
*
FROM
transactons
WHERE
event_date BETWEEN TO_DATE("2016-12-01")
AND TO_DATE("2021-12-31")
AND ((EXTRACT(MONTH FROM event_date) <= 12 AND EXTRACT(DAY FROM event_date) <= 15)
AND (EXTRACT(MONTH FROM event_date) <= 12 AND EXTRACT(DAY FROM event_date) >= 26))
Does anyone have any suggestions as to how to filter out Dec-15 to Dec-26 each year here?

You should specify your DBMS, because the following code can change. Please provide it and I will glade to update my answer.
For something quick and if I understand your logic:
SELECT
*
FROM
transactons
WHERE
(
MONTH(event_date) = 12
AND
DAY(event_date) BETWEEN 12 AND 26
)
You can reverse the query if you put NOT after the WHERE

Related

Using Where and group by clause

Can anyone describe how can I suppose to retrieve data using filter conditions such as both where and group by clauses of different fields through SQL ?
For instance ,
Require to take out the No of days in a month does the temperature exceeding 35 degrees celsius ?
SELECT temp, count(*)
FROM weather_data
WHERE day between '01-jun-2022' to '30-jun-2022'
GROUP BY temp > '35';
My requirement is to find out the aggregate details like total count
So I tried using group by clause , Inaddition to that , I must use few conditions to filter further ,
Hence I used conditions in where clause before group by clause
it's correct query :
SELECT temp, count(*) FROM weather_data
WHERE temp > '35' AND day between '01-jun-2022' and '30-jun-2022' GROUP BY temp
You want to aggregate your data, so as to get one result row per month. In SQL this is GROUP BY EXTRACT(YEAR FROM day), EXTRACT(MONTH FROM day). Your DBMS may have additional functions to extract a month (year + month to be precise) from a date, such as TO_CHAR(day, 'YYYY-MM'), but this is vendor specific.
Now you only want to count days with a temperature obove 35 degrees. The first idea to solve this, is a WHERE clause that limits the rows you aggregate to the ones in question:
SELECT
EXTRACT(YEAR FROM day) AS year,
EXTRACT(MONTH FROM day) AS month,
COUNT(*)
FROM mytable
WHERE temp > 35
GROUP BY EXTRACT(YEAR FROM day), EXTRACT(MONTH FROM day)
ORDER BY EXTRACT(YEAR FROM day), EXTRACT(MONTH FROM day);
The problem with this: If a month has no day above that temperature, you won't select that month, because your WHERE clause removed those rows. That may be okay with you, but if you want to show the months with a zero count, then move the condition into the aggregation function. Thus you select all months but only count days with high temperatures:
SELECT
EXTRACT(YEAR FROM day) AS year,
EXTRACT(MONTH FROM day) AS month,
COUNT(CASE WHEN temp > 35 THEN 1 END)
FROM mytable
GROUP BY EXTRACT(YEAR FROM day), EXTRACT(MONTH FROM day)
ORDER BY EXTRACT(YEAR FROM day), EXTRACT(MONTH FROM day);
How does this work? COUNT <expression> ) counts non-null occurrences. CASE WHEN temp > 35 THEN 1 END is short for CASE WHEN temp > 35 THEN 1 ELSE NULL END. And instead of 1 you could use any value that is not null, e.g. 'count me'. Or you could use SUM instead, if you like that better: SUM(CASE WHEN temp > 35 THEN 1 ELSE 0 END).
At last you want to limit the date range. Date literals in SQL look like this: DATE 'YYYY-MM-DD'. And as we sometimes deal with dates and other times with datetimes or timestamps, it has become common, not to use BETWEEN, but >= and <, so as to have the range work for all those data types:
SELECT
EXTRACT(YEAR FROM day) AS year,
EXTRACT(MONTH FROM day) AS month,
COUNT(CASE WHEN temp > 35 THEN 1 END)
FROM mytable
WHERE day >= DATE '2022-06-01'
AND day < DATE '2022-07-01'
GROUP BY EXTRACT(YEAR FROM day), EXTRACT(MONTH FROM day)
ORDER BY EXTRACT(YEAR FROM day), EXTRACT(MONTH FROM day);
Try this:
SELECT temp, count(*)
FROM weather_data
WHERE date >= '01-jun-2022' AND date<='30-jun-2022' AND temp > '35'
GROUP BY temp;

How to only add business days to a date in BigQuery?

For a given date I want to add business days to it. For example, if today is 10-17-2022 and I have a field that is 8 business days. How can I add 8 business days to 10-17-2022 which would be 10-27-2022.
Current Data:
BUSINESS_DAYS
Date
8
10-11-2022
10
10-13-2022
9
10-12-2022
Desired Output Data
BUSINESS_DAYS
Date
FINAL_DATE
8
10-11-2022
10-21-2022
10
10-13-2022
10-27-2022
9
10-12-2022
10-25-2022
As you can see we are skipping all weekends. We can ignore holidays for now.
Update:
Using
The suggest logic I got the following answer. I changed the names up.
I used:
DATE_ADD(A.PO_SENT_DATE , INTERVAL
(CAST(PREDICTED_LEAD_TIME AS INT64)
+ (date_diff(A.PO_SENT_DATE , DATE_ADD(A.PO_SENT_DATE , INTERVAL CAST(PREDICTED_LEAD_TIME AS INT64) DAY), week)* 2))
DAY) as FINAL_DATE
Update2: Using the following:
DATE_ADD(`Date`, INTERVAL
(BUSINESS_DAYS
+ (date_diff( DATE_ADD(`Date`, INTERVAL BUSINESS_DAYS DAY),`Date`, week) * 2))
DAY) as FINAL_DATE
There are instances where the result falls on the weekend. See screenshot below. 10-22-2022 falls on a Saturday.
Consider below simple solution
select *,
( select day
from unnest(generate_date_array(date, date + (div(business_days, 5) + 1) * 7)) day
where not extract(dayofweek from day) in (1, 7)
qualify row_number() over(order by day) = business_days + 1
) final_date
from your_table
if applied to sample data in your question
with your_table as (
select 8 business_days, date '2022-10-11' date union all
select 10, '2022-10-13' union all
select 9, '2022-10-12'
)
output is
The solution from #mikhailberlyant is really really cool, and very innovative. However if you have a lot of rows in your table and value of "business_days" column varies a lot, query will be less efficient especially for larger "business_days" values as implementation needs to generate entire range of array for each row, unnest it, and then do manipulation in that array.
This might help you do calculation without any array business:
select day, add_days as add_business_days,
DATE_ADD(day, INTERVAL cast(add_days +2*ceil((add_days -(5-(
(case when EXTRACT(DAYOFWEEK FROM day) = 7 then 1 else EXTRACT(DAYOFWEEK FROM day) end)
-1)))/5)+(case when EXTRACT(DAYOFWEEK FROM day) = 7 then 1 else 0 end) as int64) DAY) as final_day
from
(select parse_date('%Y-%m-%d', "2022-10-11") as day, 8 as add_days)

SQL average count postgresql

I want to find out what is the average number from table column entries (for example reservations) per year(0-10 years ago, 10-20 years ago, 20+ years ago). I know how to do the average part but I don't know how to categorize the AVG in the different group years.
i have this code
SELECT DATE_OF_RESERVATION,count(RESERVATIONID) AS RESERVATIONS
FROM RESERVATIONS
WHERE EXTRACT(YEAR FROM Current_Date) - DATE_OF_RESERVATION <= 10
GROUP BY DATE_OF_RESERVATION
This is the code for only one category (the first). I want to do this for all three at the same query but I can't figure it out.
You can use a case expression. For instance:
SELECT (CASE WHEN EXTRACT(YEAR FROM Current_Date) - DATE_OF_RESERVATION < 10
THEN '[0-10)'
WHEN EXTRACT(YEAR FROM Current_Date) - DATE_OF_RESERVATION < 20
THEN '[0-20)'
WHEN EXTRACT(YEAR FROM Current_Date) - DATE_OF_RESERVATION < 30
THEN '[0-30)'
ELSE 'More'
END) as grp,
COUNT(*) AS RESERVATIONS
FROM RESERVATIONS
GROUP BY grp;

MSSQL query for all records between two date range of current day

I might not be asking this right, but basically I need a query that when ran, returns all records entered from the 1st till the 15th of the current month. And when the 15 passes only return the records from the 16th till the end of the current month.
I've tried to build something like this but its for bigquery and not sql, and I can't seem to find something similar for mssql 2016.
select sample_id
from dbo.table
WHERE date_entered BETWEEN DATE_ADD(CURRENT_DATE(), -15, 'DAY') AND CURRENT_DATE()
or
WHERE date_entered BETWEEN CAST(eomonth(GETDATE()) AS datetime) AND CURRENT_DATE()
Regardless of the today's date, I need the 1st till today, until the 15th. Then the 16th till today, until the end of the month. Sorry I'm new to SQL.
UPDATE: I was able to solve this issue with the example provided by #GordonLinoff . Thank you Gordon!
SELECT rowguid, ModifiedDate
FROM [AdventureWorks2017].[Person].[Person]
WHERE Year(ModifiedDate) =Year(getdate()) and month(ModifiedDate) =month(getdate()) and
((day(getdate()) <= 15 and day(ModifiedDate) <=15))
Or
((day(getdate()) >= 16 and day(ModifiedDate) >=16))
The description of your logic is a bit hard to follow, but you seem to want something like this:
where date_entered >= datefromparts(year(getdate(), month(getdate(), 1)) and -- this month
(day(getdate()) <= 15 or
day(getdate()) > 15 and day(date_entered) > 15
)
This was MySQL:
SELECT *
FROM dbo.table
WHERE date BETWEEN CASE WHEN DAY(CURRENT_DATE) <= 15
THEN DATE_FORMAT(CURRENT_DATE, '%Y-%m-01')
ELSE DATE_FORMAT(CURRENT_DATE, '%Y-%m-16')
END
AND CASE WHEN DAY(CURRENT_DATE) <= 15
THEN DATE_FORMAT(CURRENT_DATE, '%Y-%m-15')
ELSE LAST_DAY(CURRENT_DATE)
END
Big Query:
SELECT *
FROM table
WHERE date BETWEEN CASE WHEN EXTRACT(DAY FROM CURRENT_DATE) <= 15
THEN DATE_TRUNC(CURRENT_DATE, MONTH)
ELSE DATE_ADD(DATE_TRUNC(CURRENT_DATE, MONTH), INTERVAL 15 DAY)
END
AND CASE WHEN EXTRACT(DAY FROM CURRENT_DATE) <= 15
THEN DATE_ADD(DATE_TRUNC(CURRENT_DATE, MONTH), INTERVAL 14 DAY)
ELSE DATE_ADD(CURRENT_DATE, INTERVAL 31 DAY)
END
This should give
date between 1 and 15
or date between 16 and last_of_the_month
I've tried to build something like this but its for bigquery
Whatever example you use - it is not working in BigQuery either!
Below is working example for BigQuery Standard SQL and uses some "tricks" to avoid using redundant code fragments
#standardSQL
SELECT sample_id
FROM `project.dataset.table`,
UNNEST([STRUCT(
EXTRACT(DAY FROM date_entered) AS day,
DATE_TRUNC(date_entered, MONTH) AS month
)])
WHERE DATE_TRUNC(CURRENT_DATE(), MONTH) = month
AND IF(
EXTRACT(DAY FROM CURRENT_DATE()) < 16,
day BETWEEN 1 AND 15,
day BETWEEN 16 AND 99
)

Querying last 5 years

I want to query all products sold in the last 5 years.
It is possible to do it like this:
select * from products
where time between sysdate-1826 and sysdate
But it there also a nicer way instead of calculating all the days and subtract it from sysdate?
SELECT *
FROM products
WHERE date_column >= add_months( sysdate, -12*5 )
or
SELECT *
FROM products
WHERE date_column >= sysdate - interval '5' year
will both give you all the rows from the last 5 years (though you would generally want to add a TRUNC to remove the time portion unless you really care whether a row was created on Feb 8, 2007 in the morning or in the afternoon).
select * from products
where time > DATE_SUB(NOW(), INTERVAL 5 YEAR)
Date sub will subtract 5 years from now