I am trying to list out a count of how many times an employeeid shows up for each date separated by lines and in the 0000 format.
Each time the specific employeeid occurs on a specific date, the count goes up. So EmployeeId 143 happens twice on 2023-01-18, so the first row is 0001, second is 0002
SELECT
FORMAT(COUNT(e.EmployeeId), '0000') AS [Count]
, e.EmployeeId
, c.CheckDate
FROM dbo.Check c
JOIN dbo.Employees e
ON e.EmployeeId = c.CreatedBy
GROUP BY c.CheckDate, e.EmployeeId
ORDER BY c.CheckDate DESC;
What I'm currently getting:
COUNT
EmployeeId
CheckDate
0002
143
2023-01-18 00:00:00.000
0002
143
2023-01-17 00:00:00.000
0002
427
2023-01-17 00:00:00.000
0007
607
2023-01-17 00:00:00.000
What I am wanting is:
COUNT
EmployeeId
CheckDate
0001
143
2023-01-18 00:00:00.000
0002
143
2023-01-18 00:00:00.000
0001
143
2023-01-17 00:00:00.000
0002
143
2023-01-17 00:00:00.000
0001
427
2023-01-17 00:00:00.000
0002
427
2023-01-17 00:00:00.000
etc.
My take of your issue here is that you are aggregating while you need a window function really.
To ensure unique values for your couples <CheckDate, EmployeeId> duplicates, you can try using the ROW_NUMBER window function.
SELECT FORMAT(ROW_NUMBER() OVER(
PARTITION BY c.CheckDate, e.EmployeeId
ORDER BY e.EmployeeId
), '0000') AS [Count]
, e.EmployeeId
, c.CheckDate
FROM dbo.Check c
INNER JOIN dbo.Employees e
ON e.EmployeeId = c.CreatedBy
ORDER BY c.CheckDate DESC;
Related
I want to generate a user login report where I want to show the users first login time and last logout time for each day of a month. The table of UserLoginSession is as below
UserLoginSessionId
UserId
LoginDate
LogoutDate
1310582
59
2021-04-30 15:49:54.997
2021-04-30 17:31:18.833
1310579
59
2021-04-30 14:53:51.460
NULL
1310575
59
2021-04-30 14:39:45.937
2021-04-30 14:52:23.150
1310569
59
2021-04-30 13:49:36.137
NULL
1300484
59
2021-04-28 15:17:48.837
NULL
1300478
59
2021-04-28 12:17:50.200
NULL
1300466
59
2021-04-28 04:23:48.697
2021-04-28 07:45:11.937
1299527
2466
2021-04-18 06:07:51.070
NULL
1299489
2466
2021-04-17 06:57:01.860
2021-04-17 06:57:28.260
1299449
2466
2021-04-16 10:16:54.730
NULL
1299442
2466
2021-04-16 10:08:30.187
2021-04-16 10:36:05.963
1299422
2466
2021-04-16 07:30:32.990
2021-04-16 10:15:25.777
The output report should be like below where if the logout date is null, it should take the end time of the day
UserId
LoginDate
LogoutDate
59
2021-04-30 13:49:36.137
2021-04-30 17:31:18.833
59
2021-04-28 04:23:48.697
2021-04-28 23:59:59.000
2466
2021-04-18 06:07:51.070
2021-04-18 23:59:59.000
2466
2021-04-17 06:57:01.860
2021-04-17 06:57:28.260
2466
2021-04-16 07:30:32.990
2021-04-16 23:59:59.000
I have tried the below query but it is giving me output in separate rows.
select UserId, case when rn1 = 1 then LoginDate end as [LoginDate], case when rn2 = 1 then LogoutDate end as [LogoutDate]
from (
select
row_number() over (partition by U.UserId, convert(date,s.LoginDate) order by s.LoginDate) as rn1,
row_number() over (partition by U.UserId, convert(date,s.LogoutDate) order by s.LogoutDate desc) as rn2,
S.*
from UserLoginSession S
where S.CreatedAt between #StartDate and #EndDate
) as SubQueryTable
where rn1 = 1 or rn2 = 1
I am not able to bring both the records in a single row in the query. How can I modify my query to achieve the desired result?
Using MIN and MAX and hacking around when LogoutDate is NULL:
SELECT UserId, CONVERT(date, LoginDate), MIN(LoginDate), ISNULL(MAX(LogoutDate), DATEADD(MS, -2, CONVERT(DATETIME,DATEADD(D, 1, CONVERT(date, LoginDate)))))
FROM UserLoginSession
GROUP BY UserId,CONVERT(date, LoginDate)
ORDER BY UserId,CONVERT(date, LoginDate)
I have a data set continuously being updated with date values that looks like this:
Part Number Product Status Phase1 Phase2 Phase3 Phase4 Phase5 Phase6
FD 2000 Maintain 2020-01-03 00:00:00.000 2020-01-08 00:00:00.000 2020-01-15 00:00:00.000 2020-01-17 00:00:00.000 2020-01-22 00:00:00.000 2020-01-31 00:00:00.000
FD 2001 Maintain 2020-01-03 00:00:00.000 2020-01-08 00:00:00.000 2020-01-15 00:00:00.000 2020-01-17 00:00:00.000 2020-01-22 00:00:00.000 2020-01-31 00:00:00.000
Basically, the table is made up of a part number and it's respective status and life cycle dates.
Then, I utilize CROSS APPLY to get transpose the different phase columns into one column. Here is the SQL syntax:
SELECT [Part Number], [Product Status], Phase, Date
FROM PLCMexample
CROSS APPLY (VALUES ('Phase1', [Phase1]),
('Phase2', [Phase2]),
('Phase3', [Phase3]),
('Phase4', [Phase4]),
('Phase5', [Phase5]),
('Phase6', [Phase6]))
CrossApplied (Phase, Date)
GO
This generates this view:
Part Number Product Status Phase Date
FD 2000 Maintain Registration Initiation 2020-01-03 00:00:00.000
FD 2000 Maintain Product Launch 2020-01-08 00:00:00.000
FD 2000 Maintain Phase Out 2020-01-15 00:00:00.000
FD 2000 Maintain Last Order 2020-01-17 00:00:00.000
FD 2000 Maintain Last Shipment 2020-01-22 00:00:00.000
FD 2000 Maintain Last Service 2020-01-31 00:00:00.000
FD 2001 Maintain Registration Initiation 2020-01-03 00:00:00.000
FD 2001 Maintain Product Launch 2020-01-08 00:00:00.000
FD 2001 Maintain Phase Out 2020-01-15 00:00:00.000
FD 2001 Maintain Last Order 2020-01-17 00:00:00.000
FD 2001 Maintain Last Shipment 2020-01-22 00:00:00.000
FD 2001 Maintain Last Service 2020-01-31 00:00:00.000
Which is all well and good, but now I need not only just a Date column for the view, but StartDate and EndDate. The StartDate would be the values in the current Date column. The EndDate would be the same Date as the StartDate of the following phase. Here's the first six rows of the view as an example of how it should look:
Part Number Product Status Phase StartDate EndDate
FD 2000 Maintain Registration Initiation 2020-01-03 00:00:00.000 2020-01-08 00:00:00.000
FD 2000 Maintain Product Launch 2020-01-08 00:00:00.000 2020-01-15 00:00:00.000
FD 2000 Maintain Phase Out 2020-01-15 00:00:00.000 2020-01-17 00:00:00.000
FD 2000 Maintain Last Order 2020-01-17 00:00:00.000 2020-01-22 00:00:00.000
FD 2000 Maintain Last Shipment 2020-01-22 00:00:00.000 2020-01-31 00:00:00.000
FD 2000 Maintain Last Service 2020-01-31 00:00:00.000 2020-01-31 00:00:00.000
As you can see, the "Registration Initiation" EndDate is the same as the StartDate of "Product Launch". The last phase, "Last Service", will have the same StartDate and EndDate.
What's the best way to handle this? Should I create a calculated column before or after the transposition? This is just a snippet, there are thousands of rows of data just like this so I would like to optimize the code.
I think you want lead():
SELECT [Part Number], [Product Status], Phase, Date,
LEAD(Date) OVER (PARTITION BY [Part Number] ORDER BY Date) as Next_Date
FROM PLCMexample CROSS APPLY
(VALUES ('Phase1', [Phase1]),
('Phase2', [Phase2]),
('Phase3', [Phase3]),
('Phase4', [Phase4]),
('Phase5', [Phase5]),
('Phase6', [Phase6])
) CrossApplied (Phase, Date);
EDIT:
If you want a default value, use the 3-argument form of LEAD():
LEAD(Date, 1, DATEADD(DAY, 100, DATE) OVER (PARTITION BY [Part Number] ORDER BY Date) as Next_Date
I have a sql query that brings back a list of references (products) that were at a specific status and an effective date. Unfortunately when one product moves to a different status the system doesn't put an end date in, so I am wanting to generate the end date, based on the effective date and sequence number. Is this possible?
Product Status EffectiveDate Enddate SeqNo
10 *UC 2017-10-02 00:00:00.000 NULL 8590
584 UC 2017-02-28 00:00:00.000 NULL 8380
584 APA 2017-07-07 00:00:00.000 NULL 8620
584 APA3 2017-08-10 00:00:00.000 NULL 8630
902 *UC 2017-10-13 00:00:00.000 NULL 8590
902 APA 2017-10-13 00:00:00.000 NULL 8620
1017 *UC 2017-09-01 00:00:00.000 NULL 8590
1017 APA 2017-10-10 00:00:00.000 NULL 8620
SO I would want to return the following...
Product Status EffectiveDate EndDate SeqNo
10 *UC 2017-10-02 00:00:00.000 NULL 8590
584 UC 2017-02-28 00:00:00.000 2017-07-07 00:00:00.000 8380
584 APA 2017-07-07 00:00:00.000 2017-08-10 00:00:00.000 8620
584 APA3 2017-08-10 00:00:00.000 NULL 8630
902 *UC 2017-10-13 00:00:00.000 2017-10-13 00:00:00.000 8590
902 APA 2017-10-13 00:00:00.000 NULL 8620
1017 *UC 2017-09-01 00:00:00.000 2017-10-10 00:00:00.000 8590
1017 APA 2017-10-10 00:00:00.000 NULL 8620
Many thanks.
You can use lead() :
select t.*, lead(EffectiveDate) over (partition by product order by SeqNo) as EndDate
from table t;
However, lead() starts from version 2012 +, so you can use apply instead :
select t.*, t1.EffectiveDate as EndDate
from table t outer apply
(select top (1) t1.*
from table t1
where t1.product = t.product and t1.SeqNo > t.SeqNo
order by t1.SeqNo
) t1;
This select statement is returning all values for the timeid for each row.
The joins are joined on the correct unique values.
I have tried inner join/left outer/right outer and full also select distinct to no avail.
SELECT
timed.timeid AS [Time Number],
emp.firstname AS [First Name],
emp.surname AS [Surame],
emp.empid AS [Employee Number],
timed.ver AS [Ver],
timed.tdate AS [Date],
shifts.code AS [Code],
timed.stime AS [Start],
timed.etime AS [End],
DATEDIFF(HOUR, timed.stime, timed.etime) AS [Hours]
FROM
emp
INNER JOIN timed ON emp.divid = timed.divid
INNER JOIN shifts ON timed.shiftid = shifts.shiftid
Time Number First Name Surame Employee Number Ver Date Code Start End Hours
OPS93041 C BLOGS G100 142 30/04/2013 Nts 19:00:00 06:00:00 11
OPS93041 L SMITH I101 142 30/04/2013 Nts 19:00:00 06:00:00 11
OPS93041 M WALKER M115 142 30/04/2013 Nts 19:00:00 06:00:00 11
OPS93041 P DJANGO P965 142 30/04/2013 Nts 19:00:00 06:00:00 11
As the small example of the results above show it is adding the timeid to all of the results, and also possibly the other values other than the ones from the emp table.
Desired Output would be something like.
Time Number First Name Surame Employee Number Ver Date Code Start End Hours
OPS93041 C BLOGS G100 142 30/04/2013 Nts 19:00:00 06:00:00 11
JDY73592 L SMITH I101 142 24/03/2013 Nts 11:00:00 17:00:00 6
QJA74057 M WALKER M115 188 08/07/2013 Nts 08:00:00 15:00:00 7
PDG03845 P DJANGO P965 125 19/01/2013 Nts 22:00:00 03:00:00 5
This was resolved by grouping the data by employee so the times were relevant to the employee line rather than the shift number
I have a table name "Numerator" has 3 columns: No_Fact, Numerat and Date. Like this:
No_Fact Numerat Date
1207020015 000713 2012-07-02 00:00:00.000
1207020016 000720 2012-07-02 00:00:00.000
1207020017 000722 2012-07-02 00:00:00.000
1207020019 000723 2012-07-02 00:00:00.000
1207020022 000724 2012-07-02 00:00:00.000
1207020021 000733 2012-07-02 00:00:00.000
1207020020 000734 2012-07-02 00:00:00.000
1207020018 000735 2012-07-02 00:00:00.000
1208120001 000766 2012-08-12 00:00:00.000
1208120002 000769 2012-08-12 00:00:00.000
1208230001 000777 2012-08-23 00:00:00.000
1208230002 000780 2012-08-23 00:00:00.000
I want to view some missing numbers between numbers inside Numerat column, so I have tried using the code that is:
SELECT A.Numerat+1 AS 'MISSING FROM', MIN(B.Numerat)-1 AS 'TO'
FROM Numerator A, Numerator B
WHERE A.Numerat < B.Numerat
GROUP BY A.Numerat
HAVING A.Numerat+1 < MIN(B.Numerat)
ORDER BY 1
And result set:
MISSING FROM TO
714 719
721 721
725 732
736 765
767 768
770 776
778 779
This is a code that nice.
But the sequence numbers is too many, to be incompatible with the need to be concise. So I only want to show part rows today (2012-08-23) only, likes this:
MISSING FROM TO
778 779
I am very grateful to anyone who can decode it, Thank You.
There's an interesting thing when the next line in the insert in the table,
I show began on August 23 2012:
No_Fact Numerat Date
1208230001 000777 2012-08-23 00:00:00.000
1208230002 000780 2012-08-23 00:00:00.000
1208250001 000782 2012-08-25 00:00:00.000
1208250002 000783 2012-08-25 00:00:00.000
1208250003 000784 2012-08-25 00:00:00.000
1208250004 000785 2012-08-25 00:00:00.000
1208250005 000786 2012-08-25 00:00:00.000
1208250006 000788 2012-08-25 00:00:00.000
1208250007 000789 2012-08-25 00:00:00.000
1208250008 000790 2012-08-25 00:00:00.000
1208250009 000793 2012-08-25 00:00:00.000
1208250010 000794 2012-08-25 00:00:00.000
As my original purpose, that I want to see the missing numbers in the Numerat column and to summarily I only just wanted to show a line I enter this day alone, then with advice from bluefeet I use the following code:
SELECT A.Numerat+1 AS 'MISSING FROM', MIN(B.Numerat)-1 AS 'TO'
FROM Numerator A
INNER JOIN Numerator B
ON A.Numerat < B.Numerat
AND a.Tanggal = DATEADD(DAY, DATEDIFF(DAY, 0, GetDate()), 0)
GROUP BY A.Numerat
HAVING A.Numerat+1 < MIN(B.Numerat)
ORDER BY 1
and achieving results:
MISSING FROM TO
787 787
791 792
If we look carefully there is a missing number that does not appear, that is:
MISSING FROM TO
781 781
But we do not know exactly, including the date do it? Is 23 or 25. In this case it is not important to know exactly falls on what the date this missing number, obviously there is one number missing, it should be noted, and due on the 24th of all public holidays, let us enter it on the 25th. Can anyone help?
Here are a few different ways to do this query, all have incorporated the date into it:
SELECT A.Numerat+1 AS 'MISSING FROM', MIN(B.Numerat)-1 AS 'TO'
FROM test A
INNER JOIN test B
ON A.Numerat < B.Numerat
AND a.dt = DATEADD(DAY, DATEDIFF(DAY, 0, GetDate()), 0)
GROUP BY A.Numerat
HAVING A.Numerat+1 < MIN(B.Numerat)
ORDER BY 1
See SQL Fiddle with Demo
Or
;with cte as
(
select numerat, dt,
row_number() over(partition by dt order by numerat) rn
from test
where dt = DATEADD(DAY, DATEDIFF(DAY, 0, GetDate()), 0)
)
select c.Numerat+1 MissingFrom, t.Numerat-1 [To]
from cte c
inner join test t
on c.Numerat < t.Numerat
where c.rn = 1
See SQL Fiddle with Demo
Or you can use a MAX() aggregate with no date:
SELECT max([Missing From]), max([to])
FROM
(
SELECT A.Numerat+1 AS 'MISSING FROM', MIN(B.Numerat)-1 AS 'TO'
FROM test A
INNER JOIN test B
ON A.Numerat < B.Numerat
GROUP BY A.Numerat
HAVING A.Numerat+1 < MIN(B.Numerat)
) x
See SQL Fiddle with Demo