I have a column in my SQL Server 2017 database which stores a date as datetime. I have a SQL query to select all products that where sold in specific date range unfortunately no data is returned. Data is only returned when I hardcode the input parameters in my SQL.
SQL query is as below, I also tried try_convert function
SELECT product_name, date_sold
FROM .......
WHERE date_sold BETWEEN CONVERT(varchar, #start_date, 23)
AND CONVERT(varchar, #end_date, 23)
Your query works correctly with parameters, as shown below.
As noted in the comments there is no need for the CONVERT, it works with or without.
I suggest that you check the initialisation of your paremeters with the query
SELECT #start_date, #end_date;
create table myTable (product_name varchar(50), date_sold datetime);
insert into myTable values('product 1','2022-03-05'),('product 2','2022-04-05');
declare #start_date date = '2022-04-01';
declare #end_date date = '2022-04-10';
SELECT #start_date, #end_date;
Select product_name, date_sold
from myTable
Where date_sold between convert(varchar,#start_date,23) and convert(varchar,#end_date,23);
(No column name) | (No column name)
:--------------- | :---------------
2022-04-01 | 2022-04-10
product_name | date_sold
:----------- | :----------------------
product 2 | 2022-04-05 00:00:00.000
declare #start_date date = '2022-04-01';
declare #end_date date = '2022-04-10';
Select product_name, date_sold
from myTable
Where date_sold between #start_date and #end_date;
product_name | date_sold
:----------- | :----------------------
product 2 | 2022-04-05 00:00:00.000
db<>fiddle here
Related
I am trying to duplicate rows by comparing the date of the current row with date of the next row for a user ID and row should be duplicated by incrementing the date where < date of the next row.
The last row of the id should increment till the lastworkingdate. If the lastworkingdate is null, should increment the date till current date.
Input:
Output expected
Please suggest if we can implement this logic using SQL Server.
I have tried the below code
WITH cte (User_ID, Start_DateMonth, Start_DateDAY, Last_working_date_text, lead_start_datemonth) AS
(SELECT User_ID,
CONVERT(date, CAST(Start_DateMonth AS varchar(50)) + '01') AS Start_DateMonth,
Start_DateDAY,
Last_working_date_text,
LEAD(CONVERT(datetime, CAST(Start_DateMonth AS varchar(MAX)) + '01')) OVER (PARTITION BY User_ID
ORDER BY CONVERT(date, CAST(Start_DateMonth AS varchar(50)) + '01')) AS lead_start_datemonth
FROM [dbo].[Historic_Headcount3] --mytable
UNION ALL
SELECT User_ID,
CONVERT(date, DATEADD(MONTH, 1, ISNULL(Start_DateMonth, GETDATE()))),
Start_DateDAY,
Last_working_date_text,
CONVERT(datetime, CAST(lead_start_datemonth AS varchar(MAX)) + '01') AS lead_start_datemonth
FROM cte
WHERE DATEADD(MONTH, 1, Start_DateMonth) < ISNULL(lead_start_datemonth,
CASE
WHEN ISDATE(Last_working_date_text) = 1
AND Last_working_date_text != '#' THEN CONVERT(date, Last_working_date_text)
ELSE GETDATE()
END))
SELECT User_ID,
Start_DateMonth,
Start_DateDAY,
Last_working_date_text
FROM cte
ORDER BY User_ID,
Start_DateMonth;
I am getting error
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
This script will hopefully give you enough understanding of how to utilise a numbers table to increment your months, so that you can apply it once you get your data cleaning and transformation working as required:
-- Define test data
declare #t table(UserID int, StartDate date, EndDate date);
insert into #t values(1,'20190901','20200217'),(2,'20200202','20200205'),(3,'20200108',null);
-- Find maximum possible number of Month interations required
declare #Months int = (select datediff(month,min(StartDate),getdate())+1 from #t);
-- Query the data
with t(t) as(select t from (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t(t)) -- Create a table with 10 rows in
,n(n) as(select top(#Months) row_number() over (order by (select null))-1 from t t1,t t2,t t3,t t4) -- Cross Join the table to itself to return a row_number() up to a possible 10*10*10*10 = 10,000 rows. Use TOP to limit this to what is actually required.
select t.UserID
,dateadd(month,n.n,t.StartDate) as StartDateMonth
,isnull(t.EndDate,getdate()) as EndDate
from #t as t
join n
on dateadd(month,n.n,t.StartDate) <= isnull(t.EndDate,getdate()) -- JOIN the dates to the row_number, incrementing the months as required
order by UserID
,StartDateMonth;
Output:
+--------+----------------+------------+
| UserID | StartDateMonth | EndDate |
+--------+----------------+------------+
| 1 | 2019-09-01 | 2020-02-17 |
| 1 | 2019-10-01 | 2020-02-17 |
| 1 | 2019-11-01 | 2020-02-17 |
| 1 | 2019-12-01 | 2020-02-17 |
| 1 | 2020-01-01 | 2020-02-17 |
| 1 | 2020-02-01 | 2020-02-17 |
| 2 | 2020-02-02 | 2020-02-05 |
| 3 | 2020-01-08 | 2020-02-26 |
| 3 | 2020-02-08 | 2020-02-26 |
+--------+----------------+------------+
The code worked for me
with cte ([CountryId],[Is_EO_EmployeeId],[DepartmentId],[FunctionId],[Employee_StatusId],[Event_ReasonId],User_ID, Start_DateMonth, Start_DateDAY, Last_working_date_text, lead_start_datemonth) as (
SELECT [CountryId],[Is_EO_EmployeeId],[DepartmentId],[FunctionId],[Employee_StatusId],[Event_ReasonId], User_ID, Start_DateMonth,Start_DateDAY,Last_working_date_text, CASE WHEN lead_start_datemonth IS NULL THEN NULL ELSE Convert(datetime, CAST(lead_start_datemonth AS Nvarchar(max))+'01')END AS lead_start_datemonth FROM (
select
[CountryId],
[Is_EO_EmployeeId],
[DepartmentId],
[FunctionId],
[Employee_StatusId],
[Event_ReasonId],
User_ID,
CONVERT(datetime, CAST(Start_DateMonth AS varchar(50)) + '01') AS Start_DateMonth,
Start_DateDAY,
Last_working_date_text,
lead(Start_DateMonth) over(partition by User_ID order by CONVERT(datetime, CAST(Start_DateMonth AS varchar(50)) + '01')) lead_start_datemonth
from [dbo].[Historic_Headcount3]) T--mytable
union all
select
[CountryId],
[Is_EO_EmployeeId],
[DepartmentId],
[FunctionId],
[Employee_StatusId],
[Event_ReasonId],
User_ID,
Convert(datetime,DateAdd(month,1, ISNULL(Start_DateMonth,GetDate()))),
Start_DateDAY,
Last_working_date_text,
lead_start_datemonth
from cte
where DateAdd(month,1, Start_DateMonth) < ISNULL(lead_start_datemonth,CASE WHEN ISDATE(Last_working_date_text)=1 AND Last_working_date_text != '#' THEN CONVERT(datetime,Last_working_date_text) ELSE GETDATE() END)
)
select [CountryId],[Is_EO_EmployeeId],[DepartmentId],[FunctionId],[Employee_StatusId],[Event_ReasonId],User_ID, LEFT(CONVERT(varchar, Start_DateMonth,112),6) AS Start_DateMonth, Start_DateDAY ,Last_working_date_text from cte order by User_ID, Start_DateMonth OPTion (maxrecursion 0)
I want to select all the free time other that the mentioned ones for which the room is free.
eg table:
room starttime endtime date
1 | 12pm | 1pm | 2018-02-18 00:00:00.000
1 | 2pm | 3pm | 2018-02-18 00:00:00.000
1 | 3pm | 5pm | 2018-02-18 00:00:00.000
expected output eg:
freetime
6-12,5-10
Is this even possible?
Thanks in advance.
This is for a assignment where the room is booked for a class for particular starttime(date) and endtime(date) and date.
I need to find out the times when the class will be free.
Above free timings was just an example.
Possible solution:
set dateformat ymd
-- Sample data
declare #MyTable
table (room varchar(1), starttime varchar(4), endtime varchar(4), [date] datetime)
insert into #MyTable values ('1', '12pm', '1pm', '2018-02-18 00:00:00.000')
insert into #MyTable values ('1', '2pm', '3pm', '2018-02-18 00:00:00.000')
insert into #MyTable values ('1', '3pm', '5pm', '2018-02-18 00:00:00.000')
select d.[date], r.room, t.freehour
from
(select cast(dateadd(hour, number, 0) as time) as freehour
from master..spt_values where type = 'P' and number between 6 and 22) t,
(select distinct room from #MyTable) r,
(select distinct [date] as [date] from #MyTable) d
where not exists (
select 1
from #MyTable m
where m.[date] = d.[date]
and m.room = r.room
and t.freehour between cast(m.starttime as time)
and dateadd(hour,-1,cast(m.endtime as time))
)
I am working on attendance system, and below is my data in sql server database
|EmpCode|Date |WorkDate |CheckIn |CheckOut |TotalTime
|143 |2017-02-13 |2017-02-13 |20:09:02 |22:38:50 |2.496666000
|143 |2017-02-13 |2017-02-13 |22:59:19 |23:18:15 |0.315555000
|143 |2017-02-13 |2017-02-13 |23:33:47 |05:04:24 |5.510277000
|143 |2017-02-14 |2017-02-13 |02:52:38 |05:12:04 |2.323888000
|143 |2017-02-14 |2017-02-14 |20:09:26 |21:59:27 |1.833611000
|143 |2017-02-14 |2017-02-14 |22:30:10 |22:49:26 |0.321111000
|143 |2017-02-15 |2017-02-14 |05:05:05 |05:08:13 |0.052222000
-- I want the output like
|EmpCode|wrk |InTime |OutTime |TotalTime
|143 |2017-02-13 |08:09:02 PM|05:12:04 AM|10:38:00
|143 |2017-02-14 |08:09:26 PM|05:08:13 AM|02:12:00
Assuming you want those specific formats for times:
rextester: http://rextester.com/FUW31296
create table t (
EmpCode int
, Date datetime
, WorkDate datetime
, CheckIn datetime
, CheckOut datetime
, TotalTime decimal(19, 9))
insert into t values
(143,'2017-02-13','2017-02-13','20:09:02','22:38:50',2.496666000)
,(143,'2017-02-13','2017-02-13','22:59:19','23:18:15',0.315555000)
,(143,'2017-02-13','2017-02-13','23:33:47','05:04:24',5.510277000)
,(143,'2017-02-14','2017-02-13','02:52:38','05:12:04',2.323888000)
,(143,'2017-02-14','2017-02-14','20:09:26','21:59:27',1.833611000)
,(143,'2017-02-14','2017-02-14','22:30:10','22:49:26',0.321111000)
,(143,'2017-02-15','2017-02-14','05:05:05','05:08:13',0.052222000);
query:
select
EmpCode
, wrk = convert(varchar(10),WorkDate,120)
, InTime = format(cast(min(Date + CheckIn) as datetime), 'hh:mm:ss tt')
, OutTime = format(cast(max(Date + CheckOut) as datetime), 'hh:mm:ss tt')
, TotalTime = format(dateadd(minute,sum(TotalTime)*60,0), 'HH:mm:ss')
from t
group by
EmpCode
, WorkDate
results:
+---------+------------+-------------+-------------+-----------+
| EmpCode | wrk | InTime | OutTime | TotalTime |
+---------+------------+-------------+-------------+-----------+
| 143 | 2017-02-13 | 08:09:02 PM | 05:12:04 AM | 10:38:00 |
| 143 | 2017-02-14 | 08:09:26 PM | 05:08:13 AM | 02:12:00 |
+---------+------------+-------------+-------------+-----------+
select *
, datediff(minute, first_in, last_out) as Totaltime
from (
select emp_reader_id
, min(case when Event_entry.event_entry_name = 'IN' then trnevents.DT end) as Intime
, max(case when Event_entry.event_entry_name = 'OUT' then trnevents.DT end) as Outtime
, cast(min(trnevents.DT) as date) as date
from trnevents inner join Event_entry on trnevents.EventCatId=Event_entry.EventCatId
group by
emp_reader_id
, cast(trnevents.DT as date)
) as SubQueriesMustBeNamed
select EmpCode, WorkDate as wrk, min(InTime) as InTime, max(OutTime) as OutTime, Sum(TotalTime) as TotalTime
from yourtable
group by EmpCode, WorkDate
will give you the smallest InTime, the bigest OutTime and the total TotalTime from yourtable per user per day.
I need help modifying a script to find the missing RevenuePeriod by ID within a given time frame. I have found a similar script that finds the missing date for a given ID but I don't know how to modify the script where it will give the missing dates per ID.
create table #WorksheetHistory (WorksheetID [int] IDENTITY(1,1) ,ID varchar(6), RevenuePeriod datetime)
insert into #WorksheetHistory (ID,RevenuePeriod)
SELECT '000001','2015-06-01 00:00:00.00' Union All
SELECT '000001','2015-07-01 00:00:00.00' Union All
SELECT '000001','2015-11-01 00:00:00.00' Union All
SELECT '000001','2015-12-01 00:00:00.00' Union All
SELECT '000002','2015-06-01 00:00:00.00' Union All
SELECT '000002','2015-12-01 00:00:00.00'
DECLARE #EndDate datetime
DECLARE #StartDate datetime
SET #StartDate = '2015-06-01 00:00:00.00'
SET #EndDate = '2015-12-01 00:00:00.00'
;WITH Dates as
(
SELECT #StartDate AS dt
UNION ALL
SELECT DATEADD(month, 1, dt) as dt
FROM Dates
WHERE dt < (select dateadd(month,-1,#EndDate) enddate)
)
select Month(dt) as dtMonth, Year(dt) dtYear
from Dates d left outer join #WorksheetHistory w
on dateadd(month, datediff(month,0,d.dt),0) = dateadd(month, datediff(month,0,w.RevenuePeriod),0) Where RevenuePeriod is null
Drop Table #WorksheetHistory
The current output returns the following output. I realize in the script it doesnt have an ID returned, but even if I do, it would return null value as the script indicates return null dates. I don't know how to put the associated ID in it too.
dt
2015-08-01 00:00:00.000
2015-09-01 00:00:00.000
2015-10-01 00:00:00.000
My desired result would be return the Missing ID's with the respective missing dates.
ID dt
000001 2015-08-01 00:00:00.00
000001 2015-09-01 00:00:00.00
000001 2015-10-01 00:00:00.00
000002 2015-07-01 00:00:00.00
000002 2015-08-01 00:00:00.00
000002 2015-09-01 00:00:00.00
000002 2015-10-01 00:00:00.00
000002 2015-11-01 00:00:00.00
Use EXCEPT:
WITH Dates as
(
SELECT #StartDate AS dt
UNION ALL
SELECT DATEADD(month, 1, dt) as dt
FROM Dates
WHERE dt < DATEADD(m, -1, #EndDate)
)
-- all the possible combinations
SELECT w.ID, d.dt
FROM Dates d
CROSS JOIN (
SELECT ID
FROM #WorksheetHistory
GROUP BY ID
) w
EXCEPT
-- the combinations you actually have
SELECT w.ID, d.dt
FROM Dates d
JOIN #WorksheetHistory w
ON d.dt = w.RevenuePeriod;
I'm trying to setup a query to pull employee tenure reports. I have an employee status table that tracks information for each employee (e.g. -Hire Date, Term Date, Salary Change, etc.) The table looks like this:
EmployeeID | Date | Event
1 | 1/1/99 | 1
2 | 1/2/99 | 1
1 | 1/3/99 | 2
1 | 1/4/99 | 1
I used a pivot table to move the table from a vertical layout to a horizontal layout
SELECT [FK_EmployeeID], MAX([1]) AS [Hire Date], ISNULL(MAX([2]), DATEADD(d, 1, GETDATE())) AS [Term Date]
FROM DT_EmployeeStatusEvents PIVOT (MAX([Date]) FOR [EventType] IN ([1], [2])) T
GROUP BY [FK_EmployeeID]
I get a result like this:
EmployeeID | 1 | 2
1 | 1/4/99 | 1/3/99
2 | 1/2/99 | *null*
However, the problem I run into is that I need both sets of values for each employee. (We hire a lot of recurring seasonals) What I would like is a way to convert the columns to rows selecting the hire date (1) and the very next term date (2) for each employee like this:
EmployeeID | 1 | 2
1 | 1/1/99 | 1/3/99
2 | 1/2/99 | *null*
1 | 1/4/99 | *null*
Is this possible? I've looked at a lot of the PIVOT examples and they all show an aggregate function.
The problem is that you are attempting to pivot a datetime value so you are limited to using either max or min as the aggregate function. When you use those you will only return one row for each employeeid.
In order to get past this you will need to have some value that will be used during the grouping of your data - I would suggest using a windowing function like row_number(). You can make your subquery:
select employeeid, date, event
, row_number() over(partition by employeeid, event
order by date) seq
from DT_EmployeeStatusEvents
See SQL Fiddle with Demo. This creates a unique value for each employeeId and event combination. This new number will then be grouped on so you can return multiple rows. You full query will be:
select employeeid, [1], [2]
from
(
select employeeid, date, event
, row_number() over(partition by employeeid, event
order by date) seq
from DT_EmployeeStatusEvents
) d
pivot
(
max(date)
for event in ([1], [2])
) piv
order by employeeid;
See SQL Fiddle with Demo
This should get you started...
DECLARE #EMP TABLE (EMPID INT, dDATE DATETIME, EVENTTYPE INT)
INSERT INTO #EMP
SELECT 1,'1/1/99',1 UNION ALL
SELECT 2,'1/2/99',1 UNION ALL
SELECT 1,'1/3/99',2 UNION ALL
SELECT 1,'1/4/99',1
SELECT EMPID, HIRE, TERM
FROM (SELECT EMPID, dDATE, 'HIRE' AS X, ROW_NUMBER() OVER(PARTITION BY EMPID, EVENTTYPE ORDER BY DDATE) AS INSTANCE FROM #EMP WHERE EVENTTYPE=1
UNION ALL
SELECT EMPID, dDATE, 'TERM' AS X, ROW_NUMBER() OVER(PARTITION BY EMPID, EVENTTYPE ORDER BY DDATE) AS INSTANCE FROM #EMP WHERE EVENTTYPE=2) DATATABLE
PIVOT (MIN([DDATE])
FOR X IN ([HIRE],[TERM])) PIVOTTABLE