Find business days in a month using sql - 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.

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;

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)

Joining two tables based on their dates without primary keys(SQL Server 2014)

I am lost here
I have two tables
This is the Period Table
And the Days Table
Days table counts the days of an employee when he went on a vacation
Period table is a temporary table created from a lot of if else statements
What I want to do is to join Days table with the Period table grouped by their years (and possibly use aggregate functions)
----EDIT----
Here is the query for Days Table
Select COUNT(isMandatory) + COUNT(isVacation) as 'Mandatory/Sick', COUNT(isSick) as Sick,
YEAR (date) as 'Year' from datesInclusiveTable where leaveID in
(select leaveID from leaveTable where acctNo = 'M29076')
Group by YEAR (date)
You see it has aggregate functions
I would like to post the query for Period Table but it's too long and might be
too complicated to look at
If DateStarted (or DateEnded) are of data type date:
SELECT * FROM Days D
INNER JOIN Period P ON YEAR(P.DateStarted) = D.Year
Try this:
SELECT * FROM Days D
JOIN Period P ON YEAR(CONVERT(date, P.DateStarted)) = D.Year;

How to get weeks between two dates using calendar table?

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.

SQL to identify missing week

I have a database table with the following structure -
Week_End Sales
2009-11-01 43223.43
2009-11-08 4324.23
2009-11-15 64343.23
...
Week_End is a datetime column, and the date increments by 7 days with each new entry.
What I want is a SQL statement that will identify if there is a week missing in the sequence. So, if the table contained the following data -
Week_End Sales
2009-11-01 43223.43
2009-11-08 4324.23
2009-11-22 64343.73
...
The query would return 2009-11-15.
Is this possible? I am using SQL Server 2008, btw.
You've already accepted an answer so I guess you don't need this, but I was almost finished with it anyway and it has one advantage that the selected solution doesn't have: it doesn't require updating every year. Here it is:
SELECT T1.*
FROM Table1 T1
LEFT JOIN Table1 T2
ON T2.Week_End = DATEADD(week, 1, T1.Week_End)
WHERE T2.Week_End IS NULL
AND T1.Week_End <> (SELECT MAX(Week_End) FROM Table1)
It is based on Andemar's solution, but handles the changing year too, and doesn't require the existence of the Sales column.
Join the table on itself to search for consecutive rows:
select a.*
from YourTable a
left join YourTable b
on datepart(wk,b.Week_End) = datepart(wk,a.Week_End) + 1
-- No next week
where b.sales is null
-- Not the last week
and datepart(wk,a.Week_End) <> (
select datepart(wk,max(Week_End)) from YourTable
)
This should return any weeks without a next week.
Assuming your "week_end" dates are always going to be the Sundays of the week, you could try a CTE - a common table expression that lists out all the Sundays for 2009, and then do an outer join against your table.
All those rows missing from your table will have a NULL value for their "week_end" in the select:
;WITH Sundays2009 AS
(
SELECT CAST('20090104' AS DATETIME) AS Sunday
UNION ALL
SELECT
DATEADD(DAY, 7, cte.Sunday)
FROM
Sundays2009 cte
WHERE
DATEADD(DAY, 7, cte.Sunday) < '20100101'
)
SELECT
sun.Sunday 'Missing week end date'
FROM
Sundays2009 sun
LEFT OUTER JOIN
dbo.YourTable tbl ON sun.Sunday = tbl.week_end
WHERE
tbl.week_end IS NULL
I know this has already been answered, but can I suggest something really simple?
/* First make a list of weeks using a table of numbers (mine is dbo.nums(num), starting with 1) */
WITH AllWeeks AS (
SELECT DATEADD(week,num-1,w.FirstWeek) AS eachWeek
FROM
dbo.nums
JOIN
(SELECT MIN(week_end) AS FirstWeek, MAX(week_end) as LastWeek FROM yourTable) w
ON num <= DATEDIFF(week,FirstWeek,LastWeek)
)
/* Now just look for ones that don't exist in your table */
SELECT w.eachWeek AS MissingWeek
FROM AllWeeks w
WHERE NOT EXISTS (SELECT * FROM yourTable t WHERE t.week_end = w.eachWeek)
;
If you know the range you want to look over, you don't need to use the MIN/MAX subquery in the CTE.