I have this table in access
Userinfo
userid
Name
dept id
1
JJ
002
2
KK
001
Dept
deptid
Dept Name
001
Testing
002
Sorting
003
Designing
Checkinout
userid
Name
Checktime
Checktype
1
JJ
2/5/2022 7:45:10 AM
1
1
JJ
2/5/2022 18:00:10 PM
0
1
JJ
2/6/2022 6:30:00 AM
1
1
JJ
2/6/2022 18:10:30 PM
0
2
KK
2/6/2022 6:10:30 AM
1
2
KK
2/6/2022 18:20:30 PM
0
But i want to create a Inner join that will show this table
userid
Name
Deptname
In
Out
1
JJ
Sorting
2/5/2022 7:45:10 AM
2/5/2022 18:00:10 PM
1
JJ
Sorting
2/6/2022 6:30:00 AM
2/6/2022 18:10:30 PM
1
KK
Testing
2/6/2022 6:10:30 AM
2/6/2022 18:20:30 PM
This is the SQL that i used but i dont know how to put 0 as Out and 1 as In
SELECT Userinfo.userid as ID,UserInfo.Name as Name,Dept.DeptName as Dept , Checkinout.Checktime
from ( Userinfo
inner join Checkinout on Userinfo.userid = Checkinout.userid )
inner join Dept on Userinfo.DeptId =Dept.DeptId ;
Starting from the non-normalized Checkinout you can get everything but Out directly. Then add a calculated field to the query to look up the appropriate Out Checktime for each In Checktime:
Out: (SELECT TOP 1 q.Checktime FROM [Checkinout] as q WHERE (q.userid = [Checkinout].[userid]) AND (q.Checktype = 0) AND (q.Checktime > [Checkinout].[Checktime])
ORDER BY q.Checktime ASC)
SQL:SELECT Userinfo.userid, Userinfo.Username, Dept.[Dept Name], Checkinout.Checktime AS [In], (SELECT TOP 1 q.Checktime FROM [Checkinout] as q WHERE (q.userid = [Checkinout].[userid]) AND (q.Checktype = 0) AND (q.Checktime > [Checkinout].[Checktime])
ORDER BY q.Checktime ASC) AS Out
FROM (Dept INNER JOIN Userinfo ON Dept.deptid = Userinfo.[dept id]) INNER JOIN Checkinout ON Userinfo.userid = Checkinout.userid
WHERE (((Checkinout.Checktype)=1))
'I used a nested query for the calculated field and calculated Out with the business rules that each user check-in must have a corresponding and later check-out by the same user without any check-in/check-outs between.
I have a dataset about trains, it's including a table for the customers information which is a number representing an age group and the amount of travellers for that age group.
The ID represents a location which has multiple departure times, which has multiple age groups.
The data looks something like this
StationID
Time of Departure
TravellerID
Amount of travellers
1
12:13
4001
30
1
12:13
4002
15
1
19:45
4001
10
1
19:45
4002
20
I want to sum the amount of travellers for each departure
I tried to code it this way:
SELECT StationID,[Time of Departure], sum(Amount)
FROM Train_Stations AS TS
INNER JOIN DepartureData AS DD
ON DD.FK_StationID = TS.PK_StationID
INNER JOIN CustomerInfo AS CI
ON CI.FK_StationID = TS.PK_StationID
GROUP BY StationID, [Time of Departure]
The result is like this:
StationID
Time of Departure
Amount
1
12:13
75
1
12:13
75
1
19:45
75
1
19:45
75
But I want it like this:
StationID
Time of Departure
Amount
1
12:13
45
1
19:45
30
Seems, you do something different.Based on your data query is correct
WITH CTE(StationID,DEPARTURE_TIME,TRAVELLERID,AMOUNT_OF_TRAVELLERS) AS
(
SELECT 1,CAST('12:13'AS TIME),4001,30 UNION ALL
SELECT 1,CAST('12:13'AS TIME),4002,15 UNION ALL
SELECT 1,CAST('19:45'AS TIME),4001,10 UNION ALL
SELECT 1,CAST('19:45'AS TIME),4002,20
)
SELECT C.StationID,C.DEPARTURE_TIME,SUM(AMOUNT_OF_TRAVELLERS)TOTAL_TRAVELLERS
FROM CTE AS C
GROUP BY C.StationID,C.DEPARTURE_TIME
You should specify the column as DD.StationID. It will return as an expected result.
SELECT DD.StationID,DD.[Time of Departure], sum(DD.Amount)
FROM Train_Stations AS TS
INNER JOIN DepartureData AS DD
ON DD.FK_StationID = TS.PK_StationID
INNER JOIN CustomerInfo AS CI
ON CI.FK_StationID = TS.PK_StationID
GROUP BY DD.StationID, DD.[Time of Departure]
The context: a health care clinic has 2 tables: one on patient visits, and one on patient appointments. They are not 1:1; it is possible to have an appointment without a visit, or to have a visit without an appointment. The identifier for both tables is the encounter ID, enc_ID. I'm trying to outer join these tables together and to pull in patient names.
A boiled-down example of the visit table (V):
enc_ID Visit_date Patient_ID
1 2018-06-01 10
2 2018-06-02 11
And the appointment data (A):
enc_ID Appointment_time Patient_ID
1 2018-06-01 13:00 10
3 2018-06-03 14:00 12
Outer-joining these on visit_ID would produce something like:
enc_ID V.Visit_date A.Appointment_time V.Patient_ID A.Patient_ID
1 2018-06-01 2018-06-01 13:00 10 10
2 2018-06-02 NULL 11 NULL
3 NULL 2018-06-03 14:00 NULL 12
Say I want to basically combine V.Patient_ID and A.Patient_ID, and pull in patient name from another table (P), joined on Patient_ID. The desired output:
enc_ID V.Visit_date A.Appointment_time Patient_ID Patient_Name
1 2018-06-01 2018-06-01 13:00 10 Patient A
2 2018-06-02 NULL 11 Patient B
3 NULL 2018-06-03 14:00 13 Patient C
How might this be accomplished? I'm probably missing something obvious, but I don't see how I can join in P.Patient_Name without having to join it to either V.Patient_ID or A.Patient_ID, either of which would result in null patient names.
Thanks in advance!
As long as enc_ID in both tables are not nullable, you can combine those fields with a COALESCE:
SELECT
COALESCE(V.Patient_ID, A.Patient_ID) AS enc_ID,
V.Visit_date,
A.Appointment_time,
COALESCE(V.Patient_ID, A.Patient_ID) AS Patient_ID,
P.Patient_Name
FROM V
FULL JOIN A ON V.enc_ID = A.enc_ID
INNER JOIN P
ON P.Patient_ID = V.Patient_ID
OR P.Patient_ID = A.Patient_ID
-- ON P.Patient_ID = COALESCE(V.Patient_ID, A.Patient_ID) also works
You can use ISNULL to join table P.
...(Your outer join query)
LEFT JOIN P
ON P.Patient_ID = ISNULL(V.Patient_ID, A.PatientID)
I need some helps to join the tables I have currently.
Leave, Overtime And Roster's Date, EmployeeID need to match
Note: ShiftDuration is set to default value = 8.25
Note: Leave and Overtime table will only have entries when an employee applies for leave and overtime.
Employee
EmplyeeeID | Username | Password | GivenName | FamilyName | TeamID | ContactNo | StaffType
------------------------------------------------------------------------------------------
123 123 abc John Snow 1 999 1
1234 1234 abcd Jack Waller 2 223 1
12345 12345 abcde Ali Saw 1 123 1
123456 123456 abcdef Peter Peter 2 223 1
1234567 1234567 abcdeg Bryan Peter 1 333 1
Roster
Duty_ID | EmployeeID | Date | ShiftType | ShiftDuration
--------------------------------------------------------------------
2 123 2018-05-05 1 8.25
4 1234 2018-05-04 1 8.25
5 12345 2018-05-05 1 8.25
7 123456 2018-05-04 1 8.25
8 1234567 2018-05-05 1 8.25
Overtime
OTID | EmployeeID | Date | OT_Duration | OT_Reason
------------------------------------------------------------
2 1234 2018-05-04 2 Cover Duty
Leave
LeaveID | EmployeeID | Date | Duration_Off | Reason
----------------------------------------------------------
3 123 2018-05-05 2 NIL
IdealTable (Via Query)
Date | EmployeeID | GivenName | FamilyName | TeamID | ShiftType | ShiftDuration | Duration_Off | OT_Duration | Total_Hours
---------------------------------------------------------------------------------------------------------------------------------
2018-05-05 123 John Snow 1 1 8.25 2 0 6.25
2018-05-04 1234 Jack Waller 1 1 8.25 0 2 10.25
2018-05-05 12345 Ali Saw 1 1 8.25 0 0 8.25
2018-05-04 123456 Peter Peter 1 1 8.25 0 0 8.25
2018-05-05 1234567 Bryan Peter 1 1 8.25 2 0 8.25
I have 4 tables, they are Employee, Leave, Overtime, Roster
Employee
-EmployeeID (PK)
-Username
-Password
-GivenName
-FamilyName
-TeamID
-ContactNo
-StaffType
Leave
-LeaveID (PK)
-EmployeeID (FK)
-Date
-Duration_Off
-Reason
Overtime
-OTID (PK)
-EmployeeID (FK)
-Date
-OT_Duation
-OT_Reason
Roster
-DutyID (PK)
-EmployeeID (FK)
-Date
-ShiftType
-Shift Duration (Default Value = 8.25)
What I am trying to do is join the data from this 4 tables using Query
Ideal Table
-Date (From Leave, Overtime and Roster Table)
-EmployeeID (Employee Table)
-GivenName (Employee Table)
-FamilyName (Employee Table)
-TeamID (Employee Table)
-ShiftType (Roster Table)
-ShiftDuration (Roster Table)
-Duration_Off (Leave Table)
-OT_Duration (Overtime Table)
-Total_Hours (Calculation from joint table [(ShiftDuration + OT_Duration) - Duration_Off]
My database diagram design Do ignore the TimeData table as I initially wanted to use the TimeData table to achieve the IdealTable
My current query
USE [SMRT Dashboard]
GO
;With Dates
AS
(
SELECT [Date] FROM dbo.Roster
UNION
SELECT [Date] FROM dbo.Leave
UNION
SELECT [Date] FROM dbo.Overtime
),
Work_Matrix
AS
(
SELECT EmployeeID,[Date],ShiftType,ShiftDuration,CAST(NULL AS Decimal(30,2)) AS Duration_Off,CAST(NULL AS Decimal(30,2)) AS OT_Duration
FROM dbo.Roster
UNION ALL
SELECT EmployeeID,[Date], NULL, NULL,Duration_Off
FROM dbo.Leave
UNION ALL
SELECT EmployeeID,[Date],NULL,NULL,NULL,OT_Duration
FROM dbo.Overtime
)
SELECT d.[Date],
e.EmployeeID,
e.GivenName,
e.FamilyName,
e.TeamID,
w.ShiftType,
w.ShiftDuration,
w.Duration_Off,
w.OT_Duration,
w.Total_Hours
FROM Dates d
INNER JOIN
(
SELECT EmployeeID,
[Date],
MAX(ShiftType) AS ShiftType,
SUM(ShiftDuration) AS ShiftDuration,
SUM(Duration_Off) AS Duration_Off,
SUM(OT_Duration) AS OT_Duration,
SUM(ShiftDuration) + SUM(OT_Duration) - SUM(Duration_Off) AS Total_Hours
FROM Work_Matrix
GROUP BY EmployeeID,
[Date]
)w
ON d.[Date] = w.[Date]
JOIN dbo.Employee e
ON e.EmployeeID = w.EmployeeID
Current Errors:
Msg 205, Level 16, State 1, Line 4
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
I have not tested this but you may now check this. Hope your problem will be solved.
SELECT
a.EmployeeID,
a.GivenName,
a.FamilyName,
a.TeamID,
d.ShiftType,
d.ShiftDuration,
b.Duration_Off,
c.OT_Duration,
b.Date,
(d.ShiftDuration + c.OT_Duration) - b.Duration_Off as Total_Hours
FROM Employee a
INNER JOIN Roster d ON a.EmployeeID = d.EmployeeID
LEFT JOIN Leave b ON a.EmployeeID = b.EmployeeID
LEFT JOIN Overtime c ON a.EmployeeID = c.EmployeeID
I assume Date is same from all three tables (Leave, Overtime and Roster Table)
Try this query :
select
l.Date,
o.Date,
r.Date,
e.EmployeeID,
e.GivenName,
e.FamilyName,
e.TeamID,
r.ShiftType,
r.ShiftDuration,
l.Duration_Off,
o.OT_Duration,
((r.ShiftDuration+o.OT_Duration)-l.Duration_Off) as Total_Hours
FROM Employee e
INNER JOIN Leave l ON e.EmployeeID = l.EmployeeID
INNER JOIN Overtime o ON e.EmployeeID = o.EmployeeID
INNER JOIN Roster r ON r.EmployeeID = r.EmployeeID;
Try this Query ! You will get the correct output .
SELECT
e.EmployeeID AS 'Emp ID',
e.GivenName AS 'Emp Name',
l.Date AS Date,
e.FamilyName AS 'Family Name',
e.TeamID AS 'Team ID',
r.ShiftType AS 'Shift Type',
r.ShiftDuration AS 'Shift Duration',
l.Duration_Off AS 'Duration Off',
o.OT_Duration AS 'OT Duration',
(r.ShiftDuration + o.OT_Duration) - l.Duration_Off as 'Total Hours'
FROM
Employee e,
Leave l,
Overtime o,
Roster r
WHERE
e.EmployeeID = l.EmployeeID
AND
e.EmployeeID = o.EmployeeID
AND
e.EmployeeID = r.EmployeeID
I think the issue here is that an employee may have leave, may have overtime, or neither. By using INNER JOIN, you're filtering down the set of employees to ones that have Leave, and on a Roster, and have Overtime.
I created a SqlFiddle with the data you present (see here) that should get you closer.
SELECT
COALESCE(r.Date, o.Date, l.Date) as Date,
e.EmployeeID,
e.GivenName,
e.FamilyName,
e.TeamID,
r.ShiftType,
r.ShiftDuration,
IFNULL(l.Duration_Off, 0) as Duration_Off,
IFNULL(o.OT_Duration, 0) as OT_Duration,
r.ShiftDuration + IFNULL(o.OT_Duration, 0) - IFNULL(l.Duration_Off, 0) as Total_Hours
FROM Employee e
INNER JOIN Roster r on
e.EmployeeID = r.EmployeeID
LEFT JOIN Overtime o on
e.EmployeeID = o.EmployeeID
LEFT JOIN `Leave` l on
e.EmployeeID = l.EmployeeID
There's a few cavaets that this query won't solve:
If an employee has multiple leave entries or multiple overtime entries, the person will be listed N times. You can potentially use a GROUP BY statement to deal with this
The sample data in your question doesn't reconcile correctly. For example, Employe 1234 has a shift on 5/4/2018 and OT on 5/5/2018 but gets 10.25 on 5/4/2018.
If you use TimeData, this becomes a lot easier (assuming one record per date per employee):
SELECT
COALESCE(r.Date, o.Date, l.Date) as Date,
e.EmployeeID,
e.GivenName,
e.FamilyName,
e.TeamID,
r.ShiftType,
IFNULL(r.ShiftDuration, 0) as ShiftDuration,
IFNULL(l.Duration_Off, 0) as Duration_Off,
IFNULL(o.OT_Duration, 0) as OT_Duration,
IFNULL(r.ShiftDuration, 0) + IFNULL(o.OT_Duration, 0) - IFNULL(l.Duration_Off, 0) as Total_Hours
from TimeData t
INNER JOIN Employee e on
t.EmployeeID = e.EmployeeID
LEFT JOIN Roster r on
t.Duty_ID = r.Duty_ID
LEFT JOIN Overtime o on
t.OTID = o.OTID
LEFT JOIN `Leave` l on
t.LeaveID = l.LeaveID
Example SqlFiddle can be found here
SQL Server, how to find the time slot from a schedule table like I need to output first column's end time and next column's start time?
select
s, e,
Max(cid)as c_id,
ROW_NUMBER()OVER(order by CAST(s as datetime)) as row_id
from classroom
where Room like '3310' and Days like '%T%'
group by s,e
order by CAST(s as datetime)
For example:
s e c_id row_id
------- ------- ------- ------
9:30 10:45 235 1
11:00 12:15 236 2
12:30 13:45 238 3
14:00 15:15 1415 4
15:30 16:45 273 5
17:00 18:15 270 6
I need to output
10:45-11:00
12:15-12:30
13:45-14:00
Thanks
You can insert your data in a temp table and then query that temp table
select s,e,Max(cid)as c_id,
ROW_NUMBER()OVER(order by CAST(s as datetime))as row_id
into #t
from classroom
where Room like '3310' and Days like '%T%'
group by s,e
order by CAST(s as datetime)
select t1.e, t2.s
from #t t1
INNER JOIN #t t2 on t1.row_id + 1 = t2.row_id
If you want to know only when there's a time gap between one class finishing and the next starting add where t2.s > t1.e to Abhi's answer. If you need a minimum size of slot, say 15 minutes, use where DATEDIFF(mi, t1.e, t2.s) > 15.