Adding new data in columns, from another table - SQL ORACLE - sql

I have a table with some records
MASTER TABLE
x------x--------------------x-------x
| Id | PERIOD | QTY |
x------x--------------------x-------x
| 1 | 2014-01-13 | 10 |
| 2 | 2014-01-06 | 30 |
x------x--------------------x-------x
I have another table with parameters of this record (ID)
TABLE2
x------x--------------------x------------x
| Id | Parameter | Value |
x------x--------------------x------------x
| 1 | Humidty | 10 |
| 1 | Temperature | 30 |
| 2 | Humidty | 50 |
| 2 | Temperature | 40 |
x------x--------------------x------------x
As result I want this: (combine based on ID)
Result table
x------x--------------------x-------------------------x
| Id | Period | Humidty | Temperature |
x------x--------------------x-------------------------x
| 1 | 2014-01-13 | 10 | 30 |
| 2 | 2014-01-06 | 50 | 40 |
x------x--------------------x-------------------------x
How Can I do something like that? Inner join will not work I think.

Join the tables and use conditional aggregation with case to extract the 2 columns:
select t1.id, t1.period,
max(case when t2.parameter = 'Humidty' then t2.value end) Humidty,
max(case when t2.parameter = 'Temperature' then t2.value end) Temperature
from mastertable t1 inner join table2 t2
on t2.id = t1.id
group by t1.id, t1.period

You can pivot:
SELECT * FROM
(
SELECT
t_m.Id
, t_m.Period
, t_2.Parameter
, t_2.Value
FROM #tbl_Master t_m
INNER JOIN #tbl_2 t_2 ON t_2.Id = t_m.Id
)AS t
PIVOT
(
MAX(t.Value)
FOR t.Parameter IN ([Humidity], [Temperature])
)pvt
and sample data:
DECLARE #tbl_Master TABLE
(
Id int,
Period Date,
QTY int
)
DECLARE #tbl_2 TABLE
(
Id int,
Parameter varchar(30),
[Value] int
)
INSERT INTO #tbl_Master
(
Id,
Period,
QTY
)
VALUES
(1, '2014-01-13', 10)
, (2, '2014-01-06', 30)
INSERT INTO #tbl_2
(
Id ,
Parameter ,
[Value]
)
VALUES
( 1, 'Humidity', 10)
, ( 1, 'Temperature' , 30)
, ( 2, 'Humidity', 50)
, ( 2, 'Temperature' , 40)
OUTPUT:
Id Period Humidity Temperature
1 2014-01-13 10 30
2 2014-01-06 50 40

Try this
DECLARE #Mastertable AS TABLE(Id INT,PERIOD DATE,QTY INT)
INSERT INTO #Mastertable
SELECT 1 ,'2014-01-13', 10 UNION ALL
SELECT 2 ,'2014-01-06', 30
DECLARE #Childtable AS TABLE(Id INT,Parameter VARCHAR(100), Value INT)
INSERT INTO #Childtable
SELECT 1 ,'Humidty' , 10 UNION ALL
SELECT 1 ,'Temperature' , 30 UNION ALL
SELECT 2 ,'Humidty' , 50 UNION ALL
SELECT 2 , 'Temperature' , 40
SELECT Id,Period,[Humidty],[Temperature]
FROM
(
SELECT c.Id,
m.PERIOD,
Parameter,
c.Value
FROM #Mastertable m
INNER JOIN #Childtable c
ON m.Id = c.Id
) AS srC
pivot
(MAX(Value) FOR Parameter IN ([Humidty],[Temperature])
) AS PVT
Result
Id Period Humidty Temperature
----------------------------------
1 2014-01-13 10 30
2 2014-01-06 50 40

Related

Select all entries that have the same Type as the entry with the largest Date in SQL?

How do I select all entries that have the same Type as the entry with the largest Date?
I'm using SQL Server.
My table:
+----+------+-------------------------+
| id | Type | Date |
+----+------+-------------------------+
| 1 | xxx | 2020-02-25 09:11:53.000 |
| 2 | yyy | 2020-02-25 08:30:35.000 |
| 3 | xxx | 2020-02-25 07:48:17.000 |
| 4 | xxx | 2020-02-25 09:04:25.000 |
| 5 | yyy | 2020-02-25 07:59:03.000 |
The result should be:
+----+------+-------------------------+
| id | Type | Date |
+----+------+-------------------------+
| 1 | xxx | 2020-02-25 09:11:53.000 |
| 3 | xxx | 2020-02-25 07:48:17.000 |
| 4 | xxx | 2020-02-25 09:04:25.000 |
+----+------+-------------------------+
Because id =1 is the Type with the max Date.
You can use exists with correlated sub-query :
select t.*
from table t
where exists (select 1 from table t1 where t1.type = t.type and t1.id <> t.id) and
t.type = (select top (1) t1.type from table t1 order by t1.date desc);
A correlated subquery is often the most efficient method with the right index:
select t.*
from t
where t.type = (select top (1) t2.type
from t t2
order by t2.date desc
);
The best indexes are (date desc, type) and (type).
You can also do this with window functions:
select t.*
from (select t.*,
first_value(type) over (order by date desc) as last_type
from t
) t
where type = last_type;
Rather than a Self Join, you could use LAST_VALUE in a CTE and then add that to the WHERE:
WITH CTE AS(
SELECT V.ID,
V.[Type],
V.[Date],
LAST_VALUE(V.Type) OVER (ORDER BY [Date] ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS LastType
FROM (VALUES (1, 'xxx', CONVERT(datetime2(0), '2020-02-25 09:11:53.000')),
(2, 'yyy', CONVERT(datetime2(0), '2020-02-25 08:30:35.000')),
(3, 'xxx', CONVERT(datetime2(0), '2020-02-25 07:48:17.000')),
(4, 'xxx', CONVERT(datetime2(0), '2020-02-25 09:04:25.000')),
(5, 'yyy', CONVERT(datetime2(0), '2020-02-25 07:59:03.000'))) V (ID, [Type], [Date]))
SELECT CTE.ID,
CTE.[Type],
CTE.[Date]
FROM CTE
WHERE [Type] = LastType;
DB<>Fiddle
Try this:
Declare #t table (id int , types nvarchar(100),dates datetime)
insert into #t values (1,'xxx','2020-02-25 09:11:53.000')
insert into #t values (2,'yyy','2020-02-25 08:30:35.000')
insert into #t values (3,'xxx','2020-02-25 07:48:17.000')
insert into #t values (4,'xxx','2020-02-25 09:04:25.000')
insert into #t values (5,'yyy','2020-02-25 07:59:03.000')
Declare #max nvarchar(100) = (select t.types from (
select top 1 max(dates) as t,types from #t group by types
) t)
select * from #t
where types = #max
Output:
id types dates
1 xxx 2020-02-25 09:11:53.000
3 xxx 2020-02-25 07:48:17.000
4 xxx 2020-02-25 09:04:25.000

Update the Unique number for the co-related records between two columns in the group

I need to identify and update co-related records associated rank under Req_Result column as depicted below.
Table name is tblSource.
+------+-----+-----------------+---------+
| Item | key | DenseRankWrtKey | Req_Res |
+------+-----+-----------------+---------+
| a | 1 | 1 | 1 |
+------+-----+-----------------+---------+
| a | 2 | 2 | 1 |
+------+-----+-----------------+---------+
| a | 3 | 3 | 1 |
+------+-----+-----------------+---------+
| b | 2 | 2 | 1 |
+------+-----+-----------------+---------+
| b | 9 | 7 | 1 |
+------+-----+-----------------+---------+
| c | 1 | 1 | 1 |
+------+-----+-----------------+---------+
| c | 6 | 5 | 1 |
+------+-----+-----------------+---------+
| d | 5 | 4 | 4 |
+------+-----+-----------------+---------+
| e | 8 | 6 | 6 |
+------+-----+-----------------+---------+
| f | 2 | 2 | 1 |
+------+-----+-----------------+---------+
| f | 6 | 5 | 1 |
+------+-----+-----------------+---------+
Item and Key are co-related columns and DenseRankWrtKey is created by using Dense rank with respect to key. I need to assign the same DenseRankWrtKey values to all the co-related values.
Scenario explained:
Item a has the key value 1 and 1 is co-related with c as well, so all related values for a and 1 are a,b,c,f,2,3,7,6,5 hence all these values are assigned as 1 by referring DenseRank column, d and e are not further related to any other values hence its value is kept as is from DenseRank column.
I tried the queries
Update a
SET a.Req_Res = b.DenseRankWrtKey
from tblSource a
inner join tblSource b on a.DenseRankWrtKey = b.DenseRankWrtKey
which is not sufficient.
Just try for this table too : DECLARE #Table AS TABLE
(
Id INT IDENTITY(1,1) PRIMARY KEY
,Item varchar(100)
,[key] INT
,DenseRankWrtKey INT
,Req_Res INT
)
INSERT INTO #Table
(
Item
,[key]
,DenseRankWrtKey
)
VALUES
('p', 10 ,1 ),
('q', 10 ,1 ),
('r', 20 ,2 ),
('s', 30 ,3 ),
('t', 30 ,3 ),
('u', 40 ,4 ),
('v', 40 ,4 ),
('w', 40 ,4 ),
('p', 50 ,5 ),
('q', 50 ,5 ),
('r', 50 ,5 ),
('s', 50 ,5 ),
('t', 50 ,5 ),
('u', 50 ,5 ),
('v', 50 ,5 ),
('w', 50 ,5 )
I find this way easier to read and maintain
DECLARE #TestTable TABLE (Item CHAR(1), ItemKey INT, DenseRankWrtKey INT, Req_Res INT)
INSERT #TestTable (Item, ItemKey, DenseRankWrtKey) VALUES
('a' , 1 , 1)
, ('a' , 2 , 2)
, ('a' , 3 , 3)
, ('b' , 2 , 2)
, ('b' , 9 , 7)
, ('c' , 1 , 1)
, ('c' , 6 , 5)
, ('d' , 5 , 4)
, ('e' , 8 , 6)
, ('f' , 2 , 2)
, ('f' , 6 , 5)
DECLARE #OtpTable TABLE (Item CHAR(1), ItemKey INT, DenseRankWrtKey INT)
DECLARE #RC INT = 1
WHILE #RC > 0
BEGIN
DELETE #OtpTable
;WITH UpdateCTE AS (
SELECT TOP 1 * from #TestTable
WHERE Req_Res IS NULL
)
UPDATE UpdateCTE
set Req_Res = DenseRankWrtKey
OUTPUT Inserted.Item, Inserted.ItemKey, inserted.DenseRankWrtKey INTO #OtpTable
SET #RC = ##ROWCOUNT
WHILE ##ROWCOUNT > 0
UPDATE T
SET Req_Res = (SELECT TOP 1 DenseRankWrtKey FROM #OtpTable)
OUTPUT Inserted.Item, Inserted.ItemKey, inserted.DenseRankWrtKey INTO #OtpTable
FROM #TestTable T
WHERE T.Req_Res IS NULL AND EXISTS (SELECT 1 FROM #OtpTable OT WHERE (T.Item = OT.Item OR T.ItemKey = OT.ItemKey))
END
SELECT * FROM #TestTable
You can not do update in single statement.
CREATE TABLE #Table
(
Id INT
,Item varchar(30)
,[key] INT
,DenseRankWrtKey INT
,Req_Res INT
)
INSERT INTO #Table
(
Item
,[key]
,DenseRankWrtKey
)
VALUES
<YOUR DATA>
;WITH CTE
AS
(
SELECT
T.Item
,T.[Key]
,Id = RANK() OVER(order by T.DenseRankWrtKey,T.Item)
FROM
#Table AS T
)
UPDATE
T
SET
T.Id = CTE.Id
FROM
CTE
INNER JOIN #Table AS T ON T.Item = CTE.Item AND T.[key] = CTE.[key]
DECLARE #LoopVal INT = 0
,#LoopReq INT = NULL
,#LoopKey VARCHAR(50) = NULL
WHILE 1 = 1
BEGIN
SELECT TOP 1
#LoopVal = T.DenseRankWrtKey
,#LoopReq = T.Req_Res
FROM
#Table AS T
WHERE
T.DenseRankWrtKey > #LoopVal
ORDER BY
T.DenseRankWrtKey ASC
IF ##ROWCOUNT = 0
BREAK;
UPDATE T2
SET Req_Res = CASE WHEN #LoopReq IS NOT NULL THEN #LoopReq ELSE T.DenseRankWrtKey END
FROM
#Table AS T
INNER JOIN #Table AS T2 ON T.[key] = T2.[key]
WHERE
T.DenseRankWrtKey = #LoopVal
AND T2.Req_Res IS NULL
UPDATE
T
SET
T.Req_Res = CASE WHEN #LoopReq IS NOT NULL THEN #LoopReq ELSE T2.Req_Res END
FROM
#Table AS T
INNER JOIN #Table AS T2 ON T.Item = T2.Item
AND T2.Req_Res IS NOT NULL
AND T.Req_Res IS NULL
END
SELECT * FROM #Table
ORDER BY
DenseRankWrtKey
DROP TABLE #Table
GO

SQL server and STUFF with two tables

I'm facing a problem. I have two tables as below.
table 1
+----+------+
| ks | keys |
+----+------+
| 11 | 1122|
+----+------+
| 12 | 2211|
+----+------+
| 13 | 2233|
+----+------+
| 14 | 3322|
+----+------+
table 2
+----+--+-------+
| Id | ks|codes|
+----+-----------+
| 1 | 11 |aaaaa|
+----+-----------+
| 2 | 11 |bbbbb|
+----+-----------+
| 3 | 12 |aaaaa|
+----+-----------+
| 3 | 13 |ccccc|
+----+-----------+
| 4 | 12 |bbbbb|
+----+-----------+
I tried to implement a following query in order to get my required output but did not work:
SELECT ks,
STUFF (
(SELECT ', ' + t2.codes as [text()]
from table2 as t2 where t1.ks = t2.ks FOR XML PATH('')
),1,1,''
) as "codes"
from table1 t1
group by ks;
I get this table as result:
+----+------+
| ks | codes|
+----+------+
| 11 | aaaa |
+----+------+
| 11 | bbbb |
+----+------+
| 12 | cccc |
+----+------+
| 12 | dddd |
+----+------+
then this image below shows my required output:
required result
I did something wrong but I do not know what could be. Any chance someone help me? Thanks!
Try this. I think you posted the wrong output.
Create table #tbl (ks int , codes varchar(10))
Insert into #tbl values
(11 ,'aaaa'),
(12 ,'bbbb'),
(13 ,'cccc'),
(14 ,'dddd')
Create table #tbl2 (id int, ks int , codes varchar(10))
Insert into #tbl2 values
( 1 ,11 ,'aaaaa'),
( 2 ,11 ,'bbbbb'),
( 3 ,12 ,'aaaaa'),
( 3 ,13 ,'ccccc'),
( 4 ,12 ,'bbbbb')
with cte as
(Select t1.ks, t2.codes
from #tbl t1 join #tbl2 t2 on t1.ks = t2.ks)
Select ks, STUFF(
(SELECT ',' + codes FROM cte c1
where c1.ks = c2.ks FOR XML PATH ('')), 1, 1, ''
)
from cte c2
group by ks
Output:
ks
11 aaaaa,bbbbb
12 aaaaa,bbbbb
13 ccccc
I cannot say that I fully understand what is going on in your tables--especially given your output image appears to have no relation to your sample tables--but it looks like you want a comma-delimited list of sub-values from table2 that are associated with table1.
Here's a working example that I think addresses your need. You can use CROSS APPLY in these situations. Doing so allows you to return all values from table1 regardless of a matching record in table2.
DECLARE #table1 TABLE ( [ks] INT, [code] VARCHAR(10) );
DECLARE #table2 TABLE ( [id] INT, [ks] INT, [code] VARCHAR(10) );
-- populate table1 --
INSERT INTO #table1 (
[ks], [code]
)
VALUES
( 11, 'aaaa' )
, ( 12, 'bbbb' )
, ( 13, 'cccc' )
, ( 14, 'dddd' );
-- populate table two --
INSERT INTO #table2 (
[id], [ks], [code]
)
VALUES
( 1, 11, 'aaaaa' )
, ( 2, 11, 'bbbbb' )
, ( 3, 12, 'aaaaa' )
, ( 3, 13, 'ccccc' )
, ( 4, 12, 'bbbbb' );
SELECT
t1.ks, codes.codes
FROM #table1 t1
CROSS APPLY (
SELECT (
STUFF(
( SELECT ', ' + t2.code AS "text()" FROM #table2 t2 WHERE t2.ks = t1.ks FOR XML PATH ( '' ) )
, 1, 2, ''
)
) AS [codes]
) AS codes
ORDER BY
t1.ks;
Resulting Output:
ks codes
11 aaaaa, bbbbb
12 aaaaa, bbbbb
13 ccccc
14 NULL

SQL Query group by in case statement

I Have three tables like bellow
**tRole**
+--------+----------+-----------+
| RoleID | RoleCode | RoleTitle |
+--------+----------+-----------+
| 1 | Role1 | RT1 |
| 2 | Role2 | RT2 |
| 3 | Role3 | RT3 |
+--------+----------+-----------+
**tEmployee**
+-------+-------+
| EmpID | Name |
+-------+-------+
| 1 | Emp 1 |
| 2 | Emp 2 |
| 3 | Emp 3 |
+-------+-------+
**tEmployeeRole**
+-------+--------+
| EmpID | RoleID |
+-------+--------+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
| 3 | 3 |
+-------+--------+
I want a output like below ,If a role mapped with only one employee then employee name will show other wise Multiple will show.
+--------+----------+-----------+----------+
| RoleID | RoleCode | RoleTitle | Employee |
+--------+----------+-----------+----------+
| 1 | Role1 | RT1 | Multiple |
| 2 | Role2 | RT2 | Multiple |
| 3 | Role3 | RT3 | Emp 3 |
+--------+----------+-----------+----------+
I write bellow query but when I group by emp.First_Name then the result is wrong
select cr.RoleCode,cr.RoleID,
case
when count(ear.RoleID)=1 then emp.First_Name
else 'M' end as 'AssignedTO'
from tRole as cr
left outer join tEmployeeRole as ear on cr.RoleID=ear.RoleID
left outer join tEmployee as emp on ear.EmployeeID=emp.EmployeeID
group by cr.RoleCode,crRoleID,emp.First_Name
Hello You can use this query for your solution :
you need to count with partition and use distinct data
DECLARE #tRole TABLE (
RoleID INT
,RoleCode VARCHAR(50)
,RoleTitle VARCHAR(50)
)
DECLARE #tEmployee TABLE (
EmpID INT
,EmpName VARCHAR(50)
)
DECLARE #tEmployeeRole TABLE ( EmpID INT, RoleID INT )
INSERT #tRole ( RoleID, RoleCode, RoleTitle )
SELECT 1, 'Role1', 'RT1'
UNION
SELECT 2, 'Role2', 'RT2'
UNION
SELECT 3, 'Role3', 'RT3'
INSERT #tEmployee ( EmpID, EmpName )
SELECT 1, 'Epm 1'
UNION
SELECT 2, 'Epm 2'
UNION
SELECT 3, 'Epm 3'
INSERT #tEmployeeRole ( EmpID, RoleID )
SELECT 1, 1
UNION
SELECT 1, 2
UNION
SELECT 2, 1
UNION
SELECT 2, 2
UNION
SELECT 3, 3
SELECT DISTINCT tRole.RoleID
, RoleCode
, RoleTitle
, CASE WHEN COUNT(tEmployeeRole.EmpID) OVER ( PARTITION BY tEmployee.EmpID ) = 1 THEN tEmployee.EmpName ELSE 'Multiple'END [Employee]
FROM #tEmployee tEmployee
LEFT OUTER JOIN #tEmployeeRole tEmployeeRole ON tEmployeeRole.EmpID = tEmployee.EmpID
LEFT OUTER JOIN #tRole tRole ON tRole.RoleID = tEmployeeRole.RoleID
You can Modify the answer from #Pratik to add a col that lists the employees
;with CTE as(
SELECT
DISTINCT tRole.RoleID
RoleCode
, RoleTitle
, CASE WHEN COUNT(tEmployeeRole.EmpID) OVER ( PARTITION BY tEmployee.EmpID ) = 1 THEN tEmployee.EmpName ELSE 'Multiple'END [Employee]
FROM #tEmployee tEmployee
LEFT OUTER JOIN #tEmployeeRole tEmployeeRole ON tEmployeeRole.EmpID = tEmployee.EmpID
LEFT OUTER JOIN #tRole tRole ON tRole.RoleID = tEmployeeRole.RoleID
)
select *
,stuff( (select ','+EmpName from #tEmployee IE inner join #tEmployeeRole IER on IE.EmpID = IER.EmpID where IER.RoleID = CTE.rolecode for xml PATH('') ),1,1,'') AS EMList
from CTE
This query might help you out . Make a try
Your Tables Data looks like
create TABLE #tRole (RoleID INT ,RoleCode VARCHAR(50) ,RoleTitle VARCHAR(50) )
create TABLE #tEmployee (EmpID INT ,EmpName VARCHAR(50) )
create TABLE #tEmployeeRole( EmpID INT, RoleID INT )
INSERT #tRole ( RoleID, RoleCode, RoleTitle )
SELECT 1, 'Role1', 'RT1'
UNION
SELECT 2, 'Role2', 'RT2'
UNION
SELECT 3, 'Role3', 'RT3'
INSERT #tEmployee ( EmpID, EmpName )
SELECT 1, 'Epm 1'
UNION
SELECT 2, 'Epm 2'
UNION
SELECT 3, 'Epm 3'
INSERT #tEmployeeRole ( EmpID, RoleID )
SELECT 1, 1
UNION
SELECT 1, 2
UNION
SELECT 2, 1
UNION
SELECT 2, 2
UNION
SELECT 3, 3
Desired Query
;with cte as
(
select tr.roleid,tr.rolecode,tr.roletitle,te.empname
,COUNT(ter.EmpID) OVER ( PARTITION BY ter.EmpID ) as emp_count
from #tEmployee te
inner join #tEmployeeRole tER on tER.empid=te.empid
inner join #tRole tr on tr.roleid=ter.roleid
)
select distinct RoleID,RoleCode,RoleTitle
,case when emp_count>1 then 'Multiple' else empname end as Employee
from cte

Update table based on two other tables

I have 3 tables Customer, customerCategory, Attendance as shown below:
Customer:
CustomerId | CustomerCategory | Name
A1 | 2 | User1
B1 | 1 | User2
C1 | 3 | User3
CustomerCategory
CustCategoryId | CategoryName | StartTime | EndTime
1 | Category1 | 8:15 | 17:15
2 | Category2 | 7.30 | 17:30
3 | Category3 | 8.15 | 15:15
Attendance
Id | CustomerId | InTime | OutTime
1 | A1 | 7:30 | 17:30
2 | A1 | 7:30 | NULL
3 | B1 | 8.15 | NULL
4 | C1 | 8:10 | NULL
I want to update Attendance Table Outtime column to the relevant Endtime from CustomerCategory table where Attendane.Outime is NULL. I was hoping I could write a merge query but I am confused. Is there any other way I can update Attenance table to set relevant OutTime?
UPDATE Attendance
SET Attendance.OutTime = CustomerCategory.EndTime
FROM Attendance
INNER JOIN Customer
ON (Attendance.CustomerID = Customer.CustomerID)
INNER JOIN CustomerCategory
ON (Customer.CustomerCategory = CustomerCategory.CustCategoryId)
WHERE Attendance.OutTime IS NULL;
You might need to play with syntax a little bit, since I haven't been dealing with MS SQL for a while, but the basic idea is as above. Please let me know if you will have any difficulties.
Try the following using Merge:
Declare #Customer table (CustomerId varchar(5), CustomerCategory int, Name varchar(10))
insert into #CUSTOMER
select 'A1', 2, 'User1' union
select 'B1', 1, 'User2' union
select 'C1', 3, 'User3'
Declare #CustomerCategory TABLE (CustCategoryId INT, CategoryName varchar(10), StartTime time, EndTime time)
insert into #CustomerCategory
select 1, 'Category1', '8:15', '17:15' union
select 2, 'Category2', '7:30', '17:30' union
select 3, 'Category3', '8:15', '15:15'
Declare #Attendance table (Id int, CustomerId varchar(5), InTime time, OutTime time)
insert into #Attendance
select 1, 'A1', '7:30', '17:30' union
select 2, 'A1', '7:30', NULL union
select 3, 'B1', '8:15', NULL union
select 4, 'C1', '7:30', NULL
select * from #Customer
select * from #CustomerCategory
select * from #Attendance
merge #Attendance a
using
(select c.CustomerId, cc.EndTime from #Customer c
join #CustomerCategory cc on c.CustomerCategory = cc.CustCategoryId)x
on x.CustomerId = a.CustomerId
and a.OutTime is null
when matched then update
set a.OutTime = x.EndTime ;
select * from #Attendance
HTH!