Select records in the previous 12 hour window - sql-server

I have table in below structure,
Id Name Created_Date
1 AAA 10/20/2019 3:00:00
2 BBB 10/20/2019 15:00:00
3 CCC 10/21/2019 4:00:00
4 DDD 10/21/2019 18:00:00
I need single query that needs to return based on current date and time, For example:
Case 1: Current Date is 10/21/2019 and time is in AM, It needs to return Previous date (10/20/2019), Second half(10/20/2019 12:00:01 to 10/20/2019 23:59:59).
In our case, Record "BBB" needs to be return.
Case 2: Current Date is 10/21/2019 and time is in PM, It needs to return current date (10/21/2019), First half(10/21/2019 00:00:01 to 10/21/2019 11:59:59).
In our case, Record "CCC" needs to be return.

Try this,
DECLARE #Temp_Table TABLE
(
Id INT,Name VARCHAR(10),Created_Date DATETIME
)
INSERT INTO #Temp_Table
SELECT 1,'AAA','10/20/2019 3:00:00 ' UNION ALL
SELECT 2,'BBB','10/20/2019 15:00:00' UNION ALL
SELECT 3,'CCC','10/21/2019 4:00:00 ' UNION ALL
SELECT 4,'DDD','10/21/2019 18:00:00'
DECLARE #DATE_TIME DATETIME='10/21/2019 18:00:00'
SELECT *
FROM #Temp_Table
WHERE Created_Date BETWEEN IIF(DATEPART(HOUR,#DATE_TIME) >12,CAST(CAST(#DATE_TIME AS DATE) AS DATETIME),DATEADD(HOUR,12,DATEADD(DAY,-1,CAST(CAST(#DATE_TIME AS DATE) AS DATETIME))))
AND IIF(DATEPART(HOUR,#DATE_TIME) >12,DATEADD(HOUR,12,CAST(CAST(#DATE_TIME AS DATE) AS DATETIME)),CAST(CAST(#DATE_TIME AS DATE) AS DATETIME))

Try This
SELECT ID,Name, Created_Date
FROM
(
SELECT *, CASE WHEN DATEDIFF(Hour, GETDATE() ,Created_Date) < 0 AND DATEDIFF(Hour, GETDATE() ,Created_Date) >= -12 THEN Created_Date ELSE NULL END AS ComputedColumn
FROM Tbl
) X WHERE ComputedColumn IS NOT NULL
SQL FIDDLE

Related

Dates Overlapping cases for Leave System

I'm making date overlapping cases in SQL Server where I want to check a person applying for leave should get to know if 2 or more persons have already applied for leave for the those dates. Now the catch is, suppose 2 people have already taken leave as:
Person 1: 1st Feb 2020 to 2nd Feb 2020
Person 2: 1st Feb 2020 to 5th Feb 2020
Now the person 3 applying leave for 1st Feb 2020 to 5th Feb 2020 should get the leave for 3rd Feb 2020 to 5th Feb 2020.
There can be much more cases to it. How to achieve it?
So far I have made a stored procedure which returns the total no is leave applied during a period.
Eg: if my table have a record for 1st Feb to 1st Feb it will return the total no of people who have applied to those specific dates. It returns null leave applied for 1st Feb to 2nd Feb.
Stored Procedure:
ALTER procedure [dbo].[check_leave_application](
#from_date date,
#to_date date
)
as
begin
declare #total_leaves_applied int
declare #id_count int
if #from_date = #to_date
begin
select #total_leaves_applied=count(id) from leaveRequest where current_status in (0,1) and
((cast(FromDate as date) >= #from_date and (cast(FromDate as date)<=#to_date))
or (cast(ToDate as date) between #from_date and #to_date))
end
select #total_leaves_applied as total_leaves_applied
end
Table Structure:
id FromDate ToDate request_date current_status
3 2020-01-22 2020-01-23 2020-01-22 15:41:07.943 0
3 2020-01-22 2020-01-23 2020-01-22 16:01:54.787 0
I'm not sure if this is what you're looking for, but it might be a good starting point. Using Common Table Expressions (CTE), SQL Server allows you to generate a sequence of data.
You can use this to generate a table of dates and then join your Employee Leave table to it, allowing you to COUNT how many employees took leave for a given day. Knowing that number each day, you then simply take the MAX to find out if any day has been booked more than twice:
-- Just creating a temp table to simulate your data
SELECT *
INTO #EmployeeLeave
FROM (
SELECT 1 AS id, '2020-01-22' AS FromDate, '2020-01-23' AS ToDate, '2020-01-22 15:41:07.943' AS request_date, 0 AS current_status UNION ALL
SELECT 2 AS id, '2020-01-22' AS FromDate, '2020-01-23' AS ToDate, '2020-01-22 16:01:54.787' AS request_date, 0 AS current_status UNION ALL
SELECT 3 AS id, '2020-01-03' AS FromDate, '2020-01-07' AS ToDate, '2020-01-03 12:00:00.000' AS request_date, 0 AS current_status UNION ALL
SELECT 4 AS id, '2020-01-05' AS FromDate, '2020-01-09' AS ToDate, '2020-01-03 12:00:00.000' AS request_date, 0 AS current_status UNION ALL
SELECT 5 AS id, '2020-01-06' AS FromDate, '2020-01-06' AS ToDate, '2020-01-03 12:00:00.000' AS request_date, 0 AS current_status UNION ALL
SELECT 6 AS id, '2020-01-01' AS FromDate, '2020-01-02' AS ToDate, '2020-01-03 12:00:00.000' AS request_date, 0 AS current_status UNION ALL
SELECT 7 AS id, '2020-01-01' AS FromDate, '2020-01-01' AS ToDate, '2020-01-03 12:00:00.000' AS request_date, 0 AS current_status
) A
-- Try book leave from 1st to 3rd of January
DECLARE #FromDate DATE = '2020-01-01'
DECLARE #ToDate DATE = '2020-01-03';
-- Generate a Dates table
WITH Dates AS (
SELECT [Date] = #FromDate
UNION ALL
SELECT [Date] = DATEADD(DAY, 1, [Date])
FROM Dates
WHERE [Date] < #ToDate
)
-- Use dates table to get the maximum number of people that have booked leave on a particular day within #FromDate and #ToDate
SELECT
MAX(EmployeesBookedLeave) AS HighestBookedDayInInterval
FROM (
-- For each day, get number of Leave records that have been joined
SELECT
Date, COUNT(*) AS EmployeesBookedLeave
FROM Dates D
JOIN #EmployeeLeave E
-- join Leave records that contain each Date
ON D.Date BETWEEN E.FromDate AND E.ToDate
GROUP BY Date
) A
-- Clean up
DROP TABLE #EmployeeLeave
Now if HighestBookedDayInInterval is > 2, the employee cannot book that day.

Select rowset with null value in first row of group by result set

I am stuck with a problem.
I have some data likes these :
Id Creation date Creation date hour range Id vehicule Id variable Value
1 2017-03-01 9:10 2017-03-01 9:00 1 6 0.18
2 2017-03-01 9:50 2017-03-01 9:00 1 3 0.50
3 2017-03-01 9:27 2017-03-01 9:00 1 3 null
4 2017-03-01 10:05 2017-03-01 10:00 1 3 0.35
5 2017-03-01 10:17 2017-03-01 10:00 1 3 0.12
6 2017-03-01 9:05 2017-03-01 9:00 1 5 0.04
7 2017-03-01 9:57 2017-03-01 9:00 1 5 null
I need to select rowset group by Id vehicule, Id variable, Creation date hour range and order by group by Id vehicule, Id variable, Creation date where the first Value is null but second value, third value, ... is not null. So, in the sample above, the following rowset :
Id Creation date Creation date hour range Id vehicule Id variable Value
3 2017-03-01 9:27 2017-03-01 9:00 1 3 null
2 2017-03-01 9:50 2017-03-01 9:00 1 3 0.50
Could you help me please ?
Thank you
You will have no luck with a group by in this case. I would give 2 "if exists" into the where clause to filter all IDs that fit your criteria:
(for example/not tested/probably takes forever)
select *
from yourTable y1
where id in
--the id must be in all IDs, where the first value of the set is null
--same ID instead of group by
(select 1 from yourTable y2 where y1.IDs = y2.IDs and
--the first in the set
y2.createdate = (select min(createdate) from yourtable y3 with sameid) and
y2.value is null)
AND
--the id must also be in the IDs, where there are values besides the first that are not null
id in (same select but with "not min" and "not null" obviously
hope that helped :)
Include the Value field in the ORDER BY clause and it will be sorted to the top because NULL has a lower practical value than a non-NULL value.
Assuming (because your middle paragraph is hard to understand) you want all the fields output but you want the 4th and 5th columns to produce some grouping of the output, with Value = NULL at the top of each group:
SELECT Id, CreatedDate, CreatedDateHourRange, IdVehicule, IdVariable, Value
ORDER BY IdVehicule, IdVariable, Value
I don't see any need for an actual GROUP BY clause.
I think it is unclear as to whether you want to limit the NULL Value rows in each block to just one row of NULL, but if you do you would need to state the order for which the datetime columns are sorted.
indeed group by was no use here. Also I wasn't sure where your 10:00 records were going to. Does this help?
;WITH CTE_ADD_SOME_LOGIC
AS
(
SELECT Id, CreationDate ,CreationDateHourRange ,IdVehicle ,IdVariable ,Value
, CASE WHEN Value IS NULL THEN 1 ELSE 0 END AS VALUE_IS_NULL FROM tbl
),
CTE_MORE_LOGIC
AS
(
SELECT Id, CreationDate ,CreationDateHourRange ,IdVehicle ,IdVariable ,Value,VALUE_IS_NULL
, RANK() OVER (ORDER BY CreationDateHourRange,VALUE_IS_NULL) AS RN FROM CTE_ADD_SOME_LOGIC),
CTE_ORDER
AS
(
SELECT Id, CreationDate ,CreationDateHourRange ,IdVehicle ,IdVariable ,Value,VALUE_IS_NULL, RN
, ROW_NUMBER() OVER(PARTITION BY RN ORDER BY RN,IdVehicle,IdVariable,CreationDate, VALUE_IS_NULL DESC) AS HIERARCHY FROM CTE_MORE_LOGIC
)
SELECT Id, CreationDate ,CreationDateHourRange ,IdVehicle ,IdVariable ,Value FROM CTE_ORDER WHERE HIERARCHY = 1
ORDER BY Id
Try this Query
DECLARE #Nulloccurrence INT=1 -- Give like 1,2,3 value to get first null occurrence 2 for 2nd null occurrence
SELECT TOP 2 *
FROM cte
WHERE Id <= (
SELECT ID FROM
(
SELECT Id, ROW_NUMBER()OVER( Order by id) AS Seq
FROM cte
WHERE (
CASE
WHEN CAST(variableValue AS VARCHAR) IS NULL
THEN 'P'
ELSE CAST(variableValue AS VARCHAR)
END
) = 'P'
)Dt
WHERE Dt.Seq=#Nulloccurrence
)
ORDER BY 1 DESC
Expected Result
Id Creationdate Creationdatehourrange Ids vehicleId variableValue
------------------------------------------------------------------------
3 2017-03-01 9:27 2017-03-01 9:00 1 3 NULL
2 2017-03-01 9:50 2017-03-01 9:00 1 3 0.50
For 'where the first Value is null but second value, third value, ... is not null' i suppose you want to filter cases where there is a null and a not null value at [Value] within the set you group by, to decide to filter or not that grouped row. This cannot be filtered on standard WHERE clause because at WHERE clause each row is filtered with conditions relevant to that row scope only. Simply put, each row filtered cannot 'see' other rows unless you use sub-query. You need to use HAVING clause (the comment out is for 2+ null records)
This will work:
> DECLARE #mytbl TABLE(Id INT, [Creation date] DATETIME, [Creation date
> hour range] DATETIME, [Id veh] INT, [Id var] INT, Value INT )
>
> INSERT INTO #mytbl VALUES (1,'2017-03-01 9:10 ','2017-03-01 9:00 ',1,
> 6, 0.18) INSERT INTO #mytbl VALUES (2,'2017-03-01 9:50 ','2017-03-01
> 9:00 ',1, 3, 0.50) INSERT INTO #mytbl VALUES (3,'2017-03-01 9:27
> ','2017-03-01 9:00 ',1, 3, NULL) INSERT INTO #mytbl VALUES
> (4,'2017-03-01 10:05','2017-03-01 10:00',1, 3, 0.35) INSERT INTO
> #mytbl VALUES (5,'2017-03-01 10:17','2017-03-01 10:00',1, 3, 0.12)
> INSERT INTO #mytbl VALUES (6,'2017-03-01 9:05 ','2017-03-01 9:00 ',1,
> 5, 0.04) INSERT INTO #mytbl VALUES (7,'2017-03-01 9:57 ','2017-03-01
> 9:00 ',1, 5, NULL)
>
> SELECT [Id veh], [Id var],[Creation date hour range] FROM #mytbl GROUP
> BY [Id veh], [Id var],[Creation date hour range] HAVING COUNT([Id
> veh]) - COUNT(Value) = 1
> --HAVING COUNT([Id veh]) - COUNT(Value) >= 1 ORDER BY [Id veh], [Id var],[Creation date hour range]

SQL query with function

I have a table of data which i am using a count statement to get the amount of records for the submission date
example
AuditId Date Crew Shift Cast ObservedBy 2ndObserver AuditType Product
16 2017-06-27 3 Day B1974, B1975 Glen Mason NULL Identification Billet
20 2017-06-29 1 Day 9879 Corey Lundy NULL Identification Billet
21 2017-06-29 4 Day T9627, T9625 Joshua Dwyer NULL ShippingPad Tee
22 2017-06-29 4 Day NULL Joshua Dwyer NULL Identification Billet
23 2017-06-29 4 Day S9874 Joshua Dwyer NULL ShippingPad Slab
24 2017-06-29 4 Day Bay 40 Joshua Dwyer NULL Identification Billet
Basically I am using the following code to get my results
SELECT YEAR([Date]) as YEAR, CAST([Date] as nvarchar(25)) AS [Date], COUNT(*) as "Audit Count"
FROM AuditResults
where AuditType = 'Identification' AND Product = 'Billet'
group by Date
this returns example
YEAR Date Audit Count
2017 2017-06-27 1
2017 2017-06-29 3
Now I want to be able to retrieve all dates even if blank
so I would like the return to be
YEAR Date Audit Count
2017 2017-06-27 1
2017 2017-06-28 0
2017 2017-06-29 3
I have the following function I am trying to use:
ALTER FUNCTION [dbo].[fnGetDatesInRange]
(
#FromDate datetime,
#ToDate datetime
)
RETURNS #DateList TABLE (Dt date)
AS
BEGIN
DECLARE #TotalDays int, #DaysCount int
SET #TotalDays = DATEDIFF(dd,#FromDate,#ToDate)
SET #DaysCount = 0
WHILE #TotalDays >= #DaysCount
BEGIN
INSERT INTO #DateList
SELECT (#ToDate - #DaysCount) AS DAT
SET #DaysCount = #DaysCount + 1
END
RETURN
END
How do I use my select statement with this function? or is there a better way?
cheers
Try this;
ALTER FUNCTION [dbo].[fnGetDatesInRange]
(
#FromDate datetime,
#ToDate datetime
)
RETURNS #YourData TABLE ([Year] int, DateText nvarchar(25),[Audit Count] int)
AS
begin
insert into #YourData
SELECT
YEAR(allDates.[Date]) as YEAR,
CAST(allDates.[Date] as nvarchar(25)) AS [Date],
COUNT(r.Product) as "Audit Count"
from
(
SELECT
[date]=convert(datetime, CONVERT(float,d.Seq))
FROM
(
select top 100000 row_number() over(partition by 1 order by A.name) as Seq
from syscolumns A, syscolumns B
)d
)allDates
left join
AuditResults r on r.[Date]=allDates.[date] and r.AuditType = 'Identification' AND r.Product = 'Billet'
where
allDates.[Date]>=#FromDate and allDates.[Date]<=#ToDate
group by
allDates.[Date]
return
end
The key is the 'allDates' section ;
SELECT
[date]=convert(datetime, CONVERT(float,d.Seq))
FROM
(
select top 100000 row_number() over(partition by 1 order by A.name) as Seq
from syscolumns A, syscolumns B
)d
This will return all dates between 1900 and 2173 (in this example). Limit that as you need but a nice option. A ton of different ways to approach this clearly
you have to create another table calendar as (Mysql)- idea is the same on all RDBMS-
CREATE TABLE `calendar` (
`dt` DATE NOT NULL,
UNIQUE INDEX `calendar_dt_unique` (`dt`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
and fill with date data.
more details

T-SQL Get Records for this year grouped by month

I have a table of data which looks like this
ID CreatedDate
A123 2015-01-01
B124 2016-01-02
A125 2016-01-03
A126 2016-01-04
What I would like to do is group by month (as text) for this year only. I have some up with the following query but it returns data from all years not just this one:
Select Count(ID), DateName(month,createddate) from table
Where (DatePart(year,createddate)=datepart(year,getdate())
Group by DateName(month,createddate)
This returns
Count CreatedDate
4 January
Instead of
Count CreatedDate
3 January
Where have I gone wrong? I'm sure it's something to do with converting the date to month where it goes wrong
Just tested your code:
;WITH [table] AS (
SELECT *
FROM (VALUES
('A123', '2015-01-01'),
('B124', '2016-01-02'),
('A125', '2016-01-03'),
('A126', '2016-01-04')
) as t(ID, CreatedDate)
)
SELECT COUNT(ID),
DATENAME(month,CreatedDate)
FROM [table]
WHERE DATEPART(year,CreatedDate)=DATEPART(year,getdate())
GROUP BY DATENAME(month,CreatedDate)
Output was
3 January
I removed ( near WHERE
select count(id) as Count,
case when month(createddate)=1 THEN 'Januray' END as CreatedDate
from [table]
--where year(createddate)=2016 optional if you only want the 2016 count
group by month(createddate),year(createdDate)

How to create stored procedure for alternative working Saturdays?

I want to create a stored procedure for displaying working Saturdays.
For example:
Last working Saturday 08/08/2015 (dd/mm/yyyy), then next working Saturday should be 22/08/2015 (dd/mm/yyyy)
It should omit between Saturday (15/08/2015). Likewise, I want to show for particular year
Try this. The assumption is, 3rd Jan 2015 was the first working Saturday.
DECLARE #firstsaturday date = '2015-01-03'
;WITH CTE AS
(
SELECT #firstsaturday AS StartDate
UNION ALL
SELECT DATEADD(WK,2,StartDate)
FROM CTE
WHERE YEAR(StartDate) = '2015'
)
SELECT * FROM CTE
WHERE YEAR(StartDate) = '2015'
Try something like this
DECLARE #start_sat_day DATE = Dateadd(d, -( Datepart(dw, Getdate()) % 7 ), Getdate());
WITH cte
AS (SELECT #start_sat_day AS sat_days
UNION ALL
SELECT Dateadd(dd, 14, sat_days)
FROM cte
WHERE Year(sat_days) = Year(#start_sat_day))
SELECT sat_days
FROM cte
WHERE Year(sat_days) = Year(#start_sat_day)
Result :
sat_days
---------
2015-08-08
2015-08-22
2015-09-05
2015-09-19
2015-10-03
2015-10-17
2015-10-31
2015-11-14
2015-11-28
2015-12-12
2015-12-26

Resources