Date and shift time type filter in stored procedure - sql

I am using SQL Server 2016 and I have a sensor table as follow:
SensorCode
SensorStatus
Timestamp
PS01A
Active
2019-11-20 01:38:11.850
PS01B
Active
2019-11-20 02:30:09.850
PS01C
Active
2019-11-20 05:32:11.004
PS01D
Active
2019-11-20 07:38:07.997
PS01E
Active
2019-11-20 11:38:06.700
How can I filter above table with date and shift type as input parameter in stored procedure? I can make the query for filter the date but not the shift type.
For the shift type use below table as reference:
ShiftType
StartTime
EndTime
Day
06:00:00
17:59:59
Night
18:00:00
05:59:59
and here is my code
ALTER PROCEDURE [dbo].[GET_SENSOR_STATE]
#date DATE,
#shifttypeid INT,
#shifttype NVARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
IF (#shifttype = 'DAY')
SET #shifttypeid = 0
ELSE
SET #shifttypeid = 1
SELECT [SensorCode]
,[SensorStatus]
,[Timestamp]
FROM [MyTable].[dbo].[SensorState] SS
WHERE
--#date = CAST(SS.Timestamp AS DATE)
CASE #shifttypeid
WHEN 0 THEN #date = CAST(SS.Timestamp AS DATE) AND DATEPART(HH, SS.Timestamp) BETWEEN 6 AND 18
WHEN 1 THEN #date = CAST(SS.Timestamp AS DATE) AND DATEPART(HH, SS.Timestamp) BETWEEN 18 AND 6
END
END

You can't use BETWEEN 18 AND 6 it will never be true. Also for BETWEEN, the checking condition is inclusive BETWEEN 6 AND 18 will means >= 6 AND <= 18 which is not exactly what you want. It is best to use >= and <
WHERE (
CAST(SS.Timestamp AS DATE) = #date
OR (
#shifttypeid = 1
AND CAST(SS.Timestamp AS DATE) = DATEADD(DAY, 1, #date)
)
)
AND (
( -- Day Shift
#shifttypeid = 0
AND DATEPART(HH, SS.Timestamp) >= 6
AND DATEPART(HH, SS.Timestamp) < 18
)
OR ( -- Night Shift
#shifttypeid = 1
AND (
DATEPART(HH, SS.Timestamp) < 6
OR DATEPART(HH, SS.Timestamp) >= 18
)
)
)
Added condition to handle Night Shift Date
EDIT : based on #shifttypeid filter the required Timestamp accordingly.
WHERE ( -- Day Shift 06:00 to 18:00
#shifttypeid = 0
AND SS.Timestamp >= DATEADD(HOUR, 6, CAST(#date AS DATETIME))
AND SS.Timestamp < DATEADD(HOUR, 18, CAST(#date AS DATETIME))
)
OR ( -- Night Shfit 18:00 to 06:00
#shifttypeid = 1
AND SS.Timestamp >= DATEADD(HOUR, 18, CAST(#date AS DATETIME))
AND SS.Timestamp < DATEADD(HOUR, 30, CAST(#date AS DATETIME))
)

Related

Calculate quarter for dates given an example end date and quarter number

I have an issue where I need to determine fiscal quarters, but won't always know the start/end dates for the quarters. They will, however, always be 3 months long. What I will know is the ending date of the current quarter, and what quarter and year that refers to. For example, I might be given:
Current Quarter: Q4
Current Year: 2021
Current Quarter End Date: 1/31/2021
How can I get the quarter for any other date? If any of those 3 values were to change, the query still needs to provide the quarter for any given date based on those 3 parameters.
I came up with the following, which puts the last 4 years into a temp table:
DECLARE #QuarterEnd DATE = '1/31/2022'
, #CurrentQuarter INT = 1
, #CurrentYear INT = 2022
, #Counter INT = 16
, #qs INT = 0
, #qe INT = 2
, #DateToTest DATE = '12/15/2021'
CREATE TABLE #Quarters (
StartDate DATE
, EndDate DATE
, Qtr INT
, Yr INT
)
WHILE #Counter <> 0
BEGIN
INSERT INTO #Quarters VALUES (
cast(DATEADD(MONTH, DATEDIFF(MONTH, 0, #QuarterEnd)-#qe , 0) as date)
, cast(DATEADD(MONTH, DATEDIFF(MONTH, -1, #QuarterEnd)-#qs, -1) as date)
, #CurrentQuarter
, #CurrentYear
)
SET #Counter = #Counter - 1
SET #qs = #qs + 3
SET #qe = #qe + 3
SET #CurrentQuarter = CASE WHEN #CurrentQuarter = 1 THEN 4 ELSE #CurrentQuarter - 1 END
SET #CurrentYear = CASE WHEN #CurrentQuarter = 4 THEN #CurrentYear - 1 ELSE #CurrentYear END
END
SELECT #DateToTest
, (SELECT CONCAT('Q', Qtr, ' ', Yr) FROM #Quarters WHERE #DateToTest BETWEEN StartDate and EndDate)
FROM #Quarters
However, this doesn't seem to be practical when I'm running queries that will return hundreds of thousands of records.
I suppose I can throw that into a function and call it with:
SELECT MyQuarter = dbo.MyQuarterFunction(#QuarterEnd, #CurrentQuarter, #CurrentYear, #DateToTest)
There has to be a more efficient way to do this. Any suggestions?
Just create a permanent table called Quarters.
CREATE TABLE dbo.Quarters
(
StartDate date,
QuarterNumber tinyint,
FiscalYear int,
NextQuarterStartDate AS (DATEADD(MONTH, 3, StartDate))
);
INSERT dbo.Quarters(StartDate, QuarterNumber, FiscalYear)
VALUES('20200201',1,2020),
('20200501',2,2020),
('20200801',3,2020),
('20201101',4,2020),
('20210201',1,2021),
('20210501',2,2021),
('20210801',3,2021),
('20211101',4,2021),
('20220201',1,2022),
('20220501',2,2022),
('20220801',3,2022),
('20221101',4,2022);
Now any time you are given a date (like GETDATE()) you can find the other information easily:
DECLARE #date date = GETDATE();
SELECT * FROM dbo.Quarters
WHERE #date >= StartDate
AND #date < NextQuarterStartDate;
Example db<>fiddle
If you need to support multiple fiscal calendars simultaneously, just add a column (like CalendarID or CompanyID or CustomerID).
And really, you don't even need a calendar or quarters table for this. You already have a table of clients, right? Just add a column to store what month their fiscal year starts. That's really all you need.
CREATE TABLE dbo.Clients
(
ClientID int NOT NULL CONSTRAINT PK_Clients PRIMARY KEY,
Name nvarchar(200) NOT NULL CONSTRAINT UQ_ClientName UNIQUE,
FiscalYearStart tinyint NOT NULL CONSTRAINT CK_ValidMonth
CHECK (FiscalYearStart BETWEEN 1 AND 12)
);
Now let's insert a few rows with some clients with different fiscal years:
INSERT dbo.Clients(ClientID, Name, FiscalYearStart)
VALUES(1, N'ClientFeb', 2), -- fiscal year starts in February
(2, N'ClientMay', 5), -- fiscal year starts in May
(3, N'ClientNormal', 1); -- fiscal year matches calendar
Now, yes, we need a function, but let's not do any while loops or counters or #temp tables.
CREATE FUNCTION dbo.GetLast16Quarters
(
#DateToTest date,
#ClientID int
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
(
WITH n(n) AS
(
SELECT n = 1 UNION ALL
SELECT n + 1 FROM n WHERE n < 20
),
Last20Quarters(QuarterStart, FiscalYearStart) AS
(
SELECT QuarterStart = DATEADD(QUARTER, 1-n,
DATEFROMPARTS(YEAR(#DateToTest)+1, FiscalYearStart, 1)),
FiscalYearStart
FROM dbo.Clients CROSS JOIN n WHERE ClientID = #ClientID
),
Last16Quarters AS
(
SELECT TOP (16) QuarterStart,
y = YEAR(DATEADD(MONTH, 1-FiscalYearStart, QuarterStart))
FROM Last20Quarters WHERE QuarterStart < #DateToTest
ORDER BY QuarterStart DESC
)
SELECT QuarterStart,
QuarterEnd = EOMONTH(QuarterStart, 2),
FiscalYear = y,
QuarterNumber = ROW_NUMBER() OVER
(PARTITION BY y ORDER BY QuarterStart)
FROM Last16Quarters);
Then to call it:
DECLARE #DateToTest date = '20211215';
SELECT * FROM dbo.GetLast16Quarters(#DateToTest, 1);
Output:
QuarterStart
QuarterEnd
FiscalYear
QuarterNumber
2018-02-01
2018-04-30
2018
1
2018-05-01
2018-07-31
2018
2
2018-08-01
2018-10-31
2018
3
2018-11-01
2019-01-31
2018
4
2019-02-01
2019-04-30
2019
1
2019-05-01
2019-07-31
2019
2
2019-08-01
2019-10-31
2019
3
2019-11-01
2020-01-31
2019
4
2020-02-01
2020-04-30
2020
1
2020-05-01
2020-07-31
2020
2
2020-08-01
2020-10-31
2020
3
2020-11-01
2021-01-31
2020
4
2021-02-01
2021-04-30
2021
1
2021-05-01
2021-07-31
2021
2
2021-08-01
2021-10-31
2021
3
2021-11-01
2022-01-31
2021
4
Example db<>fiddle
Assuming that you have two input variables:
declare #quarter_end date = '2021-01-31';
declare #current_quarter int = 4;
You can calculate the first month of financial year:
declare #first_month_of_fy int = (month(#quarter_end) - #current_quarter * 3 + 12) % 12 + 1;
-- 2 i.e. February
And use that value to calculate the quarter and year for any date using some math:
select *
from (values
('2020-12-15'),
('2021-01-15'),
('2021-12-15'),
('2022-01-15')
) as t(testdate)
cross apply (select
(month(testdate) - #first_month_of_fy + 12) % 12 + 1
) as ca1(month_of_fy)
cross apply (select
(month_of_fy - 1) / 3 + 1,
year(dateadd(month, 12 - month_of_fy, dateadd(day, - day(testdate) + 1, testdate)))
) as ca2(fy_quarter, fy_year)
DB<>Fiddle
I ended up creating a function to handle this. Since I'm given the last day of the quarter, which quarter it is, and which year it is, I can determine the start and end date of that fiscal year. Since a quarter is always 3 months, I can also determine which months fall into which quarter.
The first 4 variables, #qa, #qb, #qc, #qd hold a comma separated list of the months within each quarter (#qa is current quarter, #qb is current quarter -1, #qc is current quarter -2, and #qd is current quarter -3)
The second 2 variables determine the first day and last day of the fiscal calendar
To get the quarter & year, I first get the month from the supplied date (#Date) and see if it's in #qa, #qb, #qc or #qd. That tells me the fiscal quarter.
Finally, I compare the given date to the start and end date of the current fiscal year, and to the 6 years prior (going back 6 years is enough for what I need)
CREATE FUNCTION [dbo].[FunctionNameHere]
(
#Date DATE
, #QuarterEnd DATE
, #CurrentQuarter INT
, #CurrentYear INT
)
RETURNS VARCHAR(7)
AS
BEGIN
DECLARE #qa VARCHAR(8) = (concat(datepart(m, dateadd(m, 0, #QuarterEnd)),',', datepart(m, dateadd(m, -1, #QuarterEnd)),',', datepart(m, dateadd(m, -2, #QuarterEnd))))
DECLARE #qb VARCHAR(8) = (concat(datepart(m, dateadd(m, -3, #QuarterEnd)),',', datepart(m, dateadd(m, -4, #QuarterEnd)),',', datepart(m, dateadd(m, -5, #QuarterEnd))))
DECLARE #qc VARCHAR(8) = (concat(datepart(m, dateadd(m, -6, #QuarterEnd)),',', datepart(m, dateadd(m, -7, #QuarterEnd)),',', datepart(m, dateadd(m, -8, #QuarterEnd))))
DECLARE #qd VARCHAR(8) = (concat(datepart(m, dateadd(m, -9, #QuarterEnd)),',', datepart(m, dateadd(m, -10, #QuarterEnd)),',', datepart(m, dateadd(m, -11, #QuarterEnd))))
DECLARE #YearStart DATE = DATEADD(d, 1, DATEADD(q, -#CurrentQuarter, #QuarterEnd))
DECLARE #YearEnd DATE = DATEADD(q, 4-#CurrentQuarter, #QuarterEnd)
DECLARE #Qtr VARCHAR(8) = CONCAT('Q', CASE WHEN DATEPART(m, #Date) IN (SELECT value FROM string_split(#qa, ',')) THEN #CurrentQuarter
WHEN DATEPART(m, #Date) IN (SELECT value FROM string_split(#qb, ',')) THEN CASE WHEN #CurrentQuarter = 1 THEN 4
WHEN #CurrentQuarter = 2 THEN 1
WHEN #CurrentQuarter = 3 THEN 2
WHEN #CurrentQuarter = 4 THEN 3 END
WHEN DATEPART(m, #Date) IN (SELECT value FROM string_split(#qc, ',')) THEN CASE WHEN #CurrentQuarter = 1 THEN 3
WHEN #CurrentQuarter = 2 THEN 4
WHEN #CurrentQuarter = 3 THEN 1
WHEN #CurrentQuarter = 4 THEN 2 END
WHEN DATEPART(m, #Date) IN (SELECT value FROM string_split(#qd, ',')) THEN CASE WHEN #CurrentQuarter = 1 THEN 2
WHEN #CurrentQuarter = 2 THEN 3
WHEN #CurrentQuarter = 3 THEN 4
WHEN #CurrentQuarter = 4 THEN 1 END
END,
' ',
CASE WHEN #Date BETWEEN #YearStart AND #YearEnd THEN #CurrentYear
WHEN #Date BETWEEN dateadd(Year, -1, #YearStart) AND dateadd(Year, -1, #YearEnd) THEN #CurrentYear - 1
WHEN #Date BETWEEN dateadd(Year, -2, #YearStart) AND dateadd(Year, -2, #YearEnd) THEN #CurrentYear - 2
WHEN #Date BETWEEN dateadd(Year, -3, #YearStart) AND dateadd(Year, -3, #YearEnd) THEN #CurrentYear - 3
WHEN #Date BETWEEN dateadd(Year, -4, #YearStart) AND dateadd(Year, -4, #YearEnd) THEN #CurrentYear - 4
WHEN #Date BETWEEN dateadd(Year, -5, #YearStart) AND dateadd(Year, -5, #YearEnd) THEN #CurrentYear - 5
WHEN #Date BETWEEN dateadd(Year, -6, #YearStart) AND dateadd(Year, -6, #YearEnd) THEN #CurrentYear - 6
ELSE 9999 END)
return #Qtr
END

Multiple counts and merge columns

I current have a query that grabs the number of parts made per hour between two dates:
DECLARE #StartDate datetime
DECLARE #EndDate datetime
SET #StartDate = '10/10/2018'
SET #EndDate = '11/11/2018'
SELECT
CONVERT(VARCHAR(10), CAST(presstimes AS DATE), 111) AS ForDate,
DATEPART(HOUR, presstimes) AS OnHour,
COUNT(*) AS Totals
FROM
partmasterlist
WHERE
((presstimes >= #StartDate AND presstimes < dateAdd(d, 1, #EndDate))
AND (((presstimes IS NOT NULL))))
GROUP BY
CONVERT(VARCHAR(10), CAST(presstimes AS DATE), 111),
DATEPART(HOUR, presstimes)
ORDER BY
CONVERT(VARCHAR(10), CAST(presstimes AS DATE), 111) ASC;
Output:
Date Hour QTY
---------------------
2018/11/06 11 16
2018/11/06 12 20
2018/11/06 13 29
2018/11/06 14 26
Now I need to add another qty column to count where "trimmingtimes" is set.
I can't figure out how to full join the date and hour columns (e.g. presstimes might have 20qty for Hour 2, but trimmingtimes is NULL for Hour 2);
Input:
ID presstimes trimmingtimes
-----------------------------------------------------------------
1 2018-10-10 01:15:23.000 2018-10-10 01:15:23.000
2 2018-10-10 01:15:23.000 NULL
3 2018-10-10 02:15:23.000 NULL
4 NULL 2018-10-10 03:15:23.000
Output:
Date hour Press QTY T QTY
------------------------------------
10/10/18 1 2 1
10/10/18 2 1 0
10/10/18 3 0 1
I suspect you want something like this:
select convert(date, v.dt) as date,
datepart(hour, v.dt) as hour,
sum(ispress) as num_press,
sum(istrim) as num_trim
from partmasterlist pml cross apply
(values (pml.presstime, 1, 0), (pml.trimmingtime, 0, 1)
) v(dt, ispress, istrim)
group by convert(date, v.dt), datepart(hour, v.dt)
order by convert(date, v.dt), datepart(hour, v.dt);
You can add a where clause for a particular range.

Ordering dates for 4 weeks

I am writing a SQL query that pulls some information for the last 4 weeks.
I am seeing two issues with my results (see below).
First problem is that when I look back four weeks, the range should be August 10 - September 6. When I order by 'Day of the Month', the dates in September get moved to the top of the results when they should actually be at the end. So my results should start from 10 (august) and end at 6 (September).
Second problem is I'm missing a few random dates (3, 4, 13, 27).
Day of the Month Number of X
1 125
2 77
5 5
6 23
10 145
11 177
12 116
14 2
15 199
16 154
17 134
18 140
19 154
21 8
22 166
23 145
24 151
25 107
26 79
28 3
29 151
30 163
31 147
Here a general version of my query:
DECLARE #startDate datetime, #endDate datetime;
SET #startDate = dateadd(day, -28, GETDATE());
SET #endDate = dateadd(day, -1, GETDATE());
Select DATEPArt(dd, Time) AS 'Day of the Month', count(*) AS ' Number of X'
from SomeTable ST
where Time >= #startDate
AND Time < #endDate
group by DATEPArt(dd, Time)
order by 'Day of the Month'
For the first problem you can order by date to get the correct date order. I use convert to get a time-free date so that the entries group correctly.
DECLARE #StartDate datetime, #EndDate datetime;
SET #StartDate = DATEADD(day, -28, GETDATE());
SET #EndDate = DATEADD(day, -1, GETDATE());
SELECT
DATEPART(dd, Convert(date, Time)) AS 'Day of the Month', COUNT(*) AS ' Number of X'
FROM SomeTable ST
WHERE Time >= #StartDate
AND Time < #EndDate
GROUP BY Convert(date, Time)
ORDER BY Convert(date, Time)
As for the missing days, this is more complicated as the data needs to be there for the group-by to work.
One option is to create a temporary table with all the dates in, then join in the data. This will still leave a row where the join does not find any data, and can get a "zero" count.
DECLARE #StartDate datetime, #EndDate datetime;
SET #StartDate = DATEADD(day, -28, GETDATE());
SET #EndDate = DATEADD(day, -1, GETDATE());
--Create temporary table with all days between the two dates
;WITH d(d) AS
(
SELECT DATEADD(DAY, n, DATEADD(DAY, DATEDIFF(DAY, 0, #StartDate), 0))
FROM ( SELECT TOP (DATEDIFF(DAY, #StartDate, #EndDate) + 1)
n = ROW_NUMBER() OVER (ORDER BY [object_id]) - 1
FROM sys.all_objects ORDER BY [object_id] ) AS n
)
--Join in our query to the table temporary table
SELECT
DATEPART(dd, d.d) AS 'Day of the Month',
COUNT(Time) AS ' Number of X'
FROM d LEFT OUTER JOIN SomeTable ST ON DATEPART(dd, d.d) = DATEPART(dd, Time)
AND Time >= #StartDate
AND Time < #EndDate
GROUP BY d.d
ORDER BY d.d

need to calculate year,month and day for closing date

I have a table called dates,
Opendate | Closedate
------------+---------------
2015-07-09 | 2016-08-10
I am expecting the output like,
opendate | closedate | diff
------------+---------------+----------------------
2015-07-09 | 2016-08-10 | 1year 1month 1day
2015-07-09 | 2016-03-01 | 8 months 20 days
2015-07-09 | 2015-07-11 | 2 days
But when I run this query:
SELECT opendate,
closedate,
Datediff(year, opendate, closedate) AS years,
Datediff(month, opendate, closedate) AS months,
Datediff(day, opendate, closedate) AS days
FROM dates
It is giving me an output like,
opendate | closedate | years | months | days
------------+---------------+-------+--------+---------
2015-07-09 | 2016-08-10 | 1 | 13 | 397
How can we calculate 1 year 1 month and 1 day
You can use Stacked CTE to find one by one the next year, month and date.
Explanation
Query Below first finds out the DATEDIFF Years of opendate and closedate and checks if the resulting date is greater than closedate. if it is, the actual year difference is DATEDIFF of Y -1. use this new date and fetch the DATEDIFF of months using the same logic and then get the difference in days.
Online Example
Query
WITH D(Opendate,Closedate)AS
(
SELECT CAST('2015-07-09' AS DATE),CAST('2016-08-10' AS DATE)
UNION ALL
SELECT CAST('2015-07-09' AS DATE),CAST('2016-03-01' AS DATE)
UNION ALL
SELECT CAST('2015-07-09' AS DATE),CAST('2015-07-11' AS DATE)
),Y AS
(
SELECT Opendate,Closedate,
CASE
WHEN DATEADD(YEAR,DATEDIFF(YEAR,Opendate,Closedate),Opendate) > Closedate
THEN DATEDIFF(YEAR,Opendate,Closedate) - 1
ELSE DATEDIFF(YEAR,Opendate,Closedate)
END Years
FROM D
), YDate as
(
SELECT Opendate,Closedate,Years,DATEADD(YEAR,Years,Opendate) as Newopendate
FROM Y
),M AS
(
SELECT Opendate,Closedate,Years,Newopendate,
CASE WHEN DATEADD(MONTH,DATEDIFF(MONTH,Newopendate,Closedate),Newopendate) > Closedate
THEN DATEDIFF(MONTH,Newopendate,Closedate) - 1
ELSE DATEDIFF(MONTH,Newopendate,Closedate)
END Months
FROM YDate
)
SELECT Opendate,Closedate,Years,Months,DATEDIFF(Day,DATEADD(MONTH,Months,Newopendate),Closedate) as days
FROM M
Result
Opendate Closedate Years Months days
09-07-2015 00:00 10-08-2016 00:00 1 1 1
09-07-2015 00:00 01-03-2016 00:00 0 7 21
09-07-2015 00:00 11-07-2015 00:00 0 0 2
SELECT opendate,
closedate,
( ( Datediff(year, opendate, closedate) + 'years' )+
(( Datediff(month, opendate, closedate) -
12 * Datediff(year, opendate, closedate)) + 'months') +
( Datediff(day, opendate, closedate) -
( Datediff(year, opendate, closedate) * 365 -
(Datediff(month, opendate, closedate) * 12) )) + 'days'
FROM dates
The logic is you concatenate the years and then deduct the no of months of a year. Similarly deduct for days as well
Create one function as Below
CREATE FUNCTION dbo.GetYearMonthDays
(
#FromDate DATETIME
)
RETURNS NVARCHAR(100)
AS
BEGIN
DECLARE #date datetime, #tmpdate datetime, #years int, #months int, #days int
SELECT #date =#FromDate
SELECT #tmpdate = #date
SELECT #years = DATEDIFF(yy, #tmpdate, GETDATE()) - CASE WHEN (MONTH(#date) > MONTH(GETDATE())) OR (MONTH(#date) = MONTH(GETDATE()) AND DAY(#date) > DAY(GETDATE())) THEN 1 ELSE 0 END
SELECT #tmpdate = DATEADD(yy, #years, #tmpdate)
SELECT #months = DATEDIFF(m, #tmpdate, GETDATE()) - CASE WHEN DAY(#date) > DAY(GETDATE()) THEN 1 ELSE 0 END
SELECT #tmpdate = DATEADD(m, #months, #tmpdate)
SELECT #days = DATEDIFF(d, #tmpdate, GETDATE())
RETURN CONVERT(varchar(10), #years) +' Years ' + CONVERT(varchar(10), #months) + ' Month ' + CONVERT(varchar(10), #days) + ' Days'
END
GO
And use is as below
SELECT opendate,
closedate,dbo.GetYearMonthDays(closedate)
FROM dates
This will give you what you wants.

How to set a specific time interval for different work shifts to retrieve data

I have two working shifts: 8:00:00 to 16:30:00 and 20:00:00 to 06:00:00.
I want to create a stored procedure that will retrieve data from an SQL table when I pass the date
this are my tables
Table1 Emp
ID DateTime EmpID
47 2014-12-05 08:00:00 1111
47 2014-12-05 08:25:00 1235
47 2014-12-05 23:55:00 4569
47 2014-12-06 00:00:00 4563
47 2014-12-06 02:00:00 7412
59 2014-12-06 04:00:00 8523
59 2014-12-05 10:30:00 5632
Table2 Product
ID DateTime ProductMade
47 2014-12-05 11:00:00 Milk
47 2014-12-05 08:00:00 Juice
47 2014-12-06 00:00:00 Bread
47 2014-12-06 06:00:00 Cakes
query for shift 2 18:00 to 06:00
SELECT *
FROM Table 1 as T1
INNER JOIN Table_Product as Prod ON t1.ID=Prod.ID
WHERE T1.DateTime BETWEEN DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()-8), 0) + '18:00'
AND DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()-7), 0) + '06:00'
so this will get all the records that has the same ID matching
then i have to do another query for the first shift.
between 08:00 to 16:30
SELECT *
FROM Table 1 AS T1
INNER JOIN
Table_Product AS Prod ON t1.ID=Prod.ID
WHERE DATEDIFF(day, CONVERT(VARCHAR(10), GETDATE(),110), CONVERT(VARCHAR(10), T1.DateTime,110))=-1 AND DATEPART(HOUR,T1.DateTime) BETWEEN '07' AND '16'
How do i make this into one stored procdure and elminate having two queries.
Try this if you want it for a specific shift. Then you have to specify #Shift
Declare #Shift char(1),
#days int
Set #Shift = 'A' -- will only get information for SHIFT A. Change to B if you want the rest
Set #days = 1
Select *
from Table1 t
where t.DateTime between
case when #Shift = 'A' then DateAdd(hour, 8, Convert(date, GetDate() - #days))
else DateAdd(hour, 20, Convert(date, GetDate() - #days)) end
and
case when #Shift = 'A' then DateAdd(hour, 16, Convert(date, GetDate() - #days))
else DateAdd(hour, 30, Convert(date, GetDate() - #days)) end
Specify the Shift and a Date, and it should work.
You can always do something like this as well. This you only have to specify the number of days in the past, and it will retrieve the information and specify the Shift in the first Column
DECLARE #days int
SET #days = 1
Select case when DATEPART(hour, t.DateTime) between 8 and 16 then 'A' else 'B' end AS Shift, *
from Table1 t
where t.DateTime between DateAdd(hour, 8, Convert(date, GetDate() - #days))
and DateAdd(hour, 30, Convert(date, GetDate() - #days))
ORDER BY 1, t.DateTime
It seems that you have two shifts per day and the day shift begins before the night shift. So, let's enumerate the shifts and let you choose the one(s) you want that way:
select t.*
from (select t.*,
row_number() over (partition by cast(sp.datetime as date)
order by sp.datetime
) as shiftnumber
from table t
) t
where DATEDIFF(day, CAST(GETDATE() as DATE), CAST(SP.DateTime as DATE)) = -1 and
shiftnumber = 1;
Note that I also changed the date arithmetic. The conversion to dates uses the built-in DATE type. Converting a date to a string and back to a date is inelegant.