How to get weeks between two dates using calendar table? - sql

I have the table table1 with two columns
start_date end_date
03/09/2016 03/15/2016
Now I need all the week start and end dates between these two dates
week_start_date week_end_date
03/07/2016 03/11/2016
03/14/2016 03/18/2016
I have the calendar table with dates and week start and enddates from jan 11.
I am trying to join with it, but its not producing the desired result.
SELECT DISTINCT r.START_DATE, r.END_DATE, c.week_start_date, c.week_end_date
FROM [table1] AS r
LEFT JOIN [Calendar] AS c
ON c.week_start_date BETWEEN r.WEEK_START_DATE AND r.WEEK_END_DATE
How can I achieve this using sql query. No procedures or t-sql please or variables.

I think the problem is the logic in the on clause:
select distinct r.START_DATE, r.END_DATE, c.week_start_date,c .week_end_date
from table1 r join
calendar c
on c.week_start_date <= r.end_date and
c.week_end_date >= r.start_date;
Notes:
The select distinct should be unnecessary (unless the calendar table is by day).
The left join is unnecessary.

Related

How to Select dates when i sold nothing?

Assume i have a table of item_sold from 01-01-2020 to 01-01-2023 with columns product_id, product_name, quantity and date.
I want to get all the dates when i sold nothing.
I am using Postgresql, please help me in this problem.
I tried withclaue and many other things but they didn't worked.
You need some kind of calendar table containing all dates which you potentially want to report. Assuming the date range be the entire years of 2020 through 2023 inclusive, we can try the following left anti-join approach:
WITH dates AS (
SELECT ('2020-01-01'::date + s.a) AS dt
FROM generate_series(0, 365*4) AS s(a)
)
SELECT d.dt
FROM dates d
LEFT JOIN yourTable t
ON t.item_sold = d.dt
WHERE t.item_sold IS NULL
ORDER BY d.dt;

How to add a set of dates for each category in a dimension?

I have data that looks like this where there is a monthly count of a particular animal for each month. By default, it aggregates in the month where there is data.
However, I would like to like to have a default set of dates for each animal up to the current month date with 0 if there's no data. Desired Result -
Is there a way to handle with a on sql server and not in Excel?
Much appreciated in advance.
You can generate the months you want using a numbers table or recursive CTE (or calendar table). Then cross join with the animals to generate the rows and use left join to bring in the existing data:
with dates as (
select min(date) as dte
from t
union all
select dateadd(month, 1 dte)
from dates
where dte < getdate()
)
select a.animal, d.dte, coalesce(t.monthly_count, 0) as monthly_count
from dates d cross join
(select distinct animal from t) a left join
data t
on t.date = d.dte and t.animal = a.animal
order by a.animal, d.dte;

Counting working days between two dates in data table using calendar table

I have a data table, which consist of 4 dates per string:
table example
Also I have calendar table with holidays and weekends for my location.
calendar table
What I need is to count number of working days for following pairs in data table:
task_work_end_date and task_got_to_work_date
task_got_to_work_date and task_assigned_date
I have tried following select, but it would always show 1 working day, because I'm putting calendar_date in front:
select data_table.*, days.work_days
from data_table
left join (
select calendar_date, count(calendar_date) as work_days
from calendar_table
where type_of_day IN ('workday', 'workday shortened')
group by calendar_date ) days
ON days.calendar_date between task_assigned_date and task_got_to_work_date
Please advise on SQL to achieve correct joining those tables.
If you are on SQL server then use OUTER APPLY as follows:
select d.*, days.work_days
from data_table d
outer apply (
select count(calendar_date) as work_days
from calendar_table c
where c.type_of_day IN ('workday', 'workday shortened')
and c.calendar_date between d.task_assigned_date and d.task_got_to_work_date) days
A lateral join is definitely one way to solve the problem (that is the apply syntax in the other answers).
A more generic answer is simply a correlated subquery:
select d.*,
(select count(*)
from calendar_table c
where c.type_of_day in ('workday', 'workday shortened') and
c.calendar_date between d.task_assigned_date and d.task_got_to_work_datework_days
) as work_days
from data_table d;
Note: If performance is an issue, there may be other approaches. If that is the case, accept one of the answers here and ask a new question.
To use a left join, you need to change how you are grouping. You can list the actual columns in data_table in the group by and the select as well.
select data_table.*, count(days.calendar_date)
from data_table
left join calendar_table days
ON days.calendar_date between task_assigned_date and task_got_to_work_date
and type_of_day IN ('workday', 'workday shortened')
group by data_table.*
Another option would be to outer apply and get the count this way:
select data_table.*, days.work_days
from data_table
outer apply (
select count(calendar_date) as work_days
from calendar_table
where type_of_day IN ('workday', 'workday shortened')
and calendar_date between task_assigned_date and task_got_to_work_date) days
Solution worked perfectly for me in POSTGRES:
table example
join
calendar table ON tsrange(task_assigned_date, task_got_to_work_date)&&tsrange(calendar.start_time, calendar.end_time)

How to Find Week Number in look up Table

I have a Two Tables
One is Lookup Table Week for WeekNumber and Weekdate
And Another is Register
What I want to Return is current WeekLabel from the Week table where Entrytime is falling between two dates
For example :
Entrytime 2016-08-15 09:02:15.0000000
is between Weekstartdate value 2016-08-15 00:00:00.000 and 2016-08-22 00:00:00.000
so I want to return WeekLabel 1 and WeekStartdate 2016-08-15 from week table and so on..
Using cross apply() to get the latest WeekStartDate that occurs before or on EntryTime.
select r.*
, x.WeekLabel
from register r
cross apply (
select top 1 w.WeekLabel
from [Week] w
where w.weekstartdate =< r.entrytime
order by w.weekstartdate desc
) as x
switch to outer apply() for left join functionality, e.g. return null if there is no corresponding WeekLabel.
You can join the tables based on the entrytime being greater than the weekstartdate; this will multiply each entry for all the preceding weeks, so you can get the latest one with a max on WeekLabel (assuming they're constantly increasing).
select t2.ID, t2.CODE, max(t1.WeekLabel)
from Week t1
join Register t2
on t2.Entrytime > t1.Weekstartdate
group by t2.ID, t2.CODE
Another option is a simple JOIN
Select R.*
,W.WeekLabel
,W.WeekStartdate
From Register R
Join [Week] W
on R.EntryTime >= W.WeekStartDate
and R.EntryTime < DateAdd(DAY,7,W.WeekStartDate)
Another option is to join to the week reference table using the datediff function:
SELECT * from
register r
join [Week] w on
DATEDIFF(day, r.entryTime, w.weekStartDate) between 0 and 7

Find business days in a month using sql

I am using java udf to exclude sat and sun to get business days.I am stuck with sql query to exclude holidays which are in another table called holidays.Please some one help me.
I have two tables which are as follows:
table1
trade_date
12-02-2013
14-02-2013
02-03-2013
25-04-2013
table2
holidays
11-02-2013
13-02-2013
02-03-2013
20-04-2013
And my output should be as follows:
trade_date business_day
12-02-2013 7
14-02-2013 8
02-03-2013 0(because it is saturday)
25-04-2013 18
I tried this query:
select d.t_date
from dates d
left outer join holidays h on (d.t_date = h.h_date)
Thanks.
One approach would be to exclude them using an in clause:
select d.t_date
from dates d
where d.t_date not in (select h.h_date from holidays)
If that doesn't work for you, just modify the current query a little:
select d.t_date
from dates d
left outer join holidays h on (d.t_date = h.h_date)
where h.h_date is null
This says that if there is not a match in the holidays table the record can be included.