sql query help - trying to get rid of temp tables - sql

I have the following tables -
Resource
--------------------
Id, ProjectId, Hours, ApproverId
Project
--------------------
Id, Name
The input is ApproverId. I need to retrieve all the rows that have matching ApproverId (simple enough). And for every resource that I get back, I also need to get their hours (same table) whose approverId is not the one that is passed in (business requirement, to be grayed out in the UI). What I'm doing right now is - get all resources based on ApproverId, stored them in a temp table, then do a distinct on Resource.Id, store it in a different temp table, and then for every Resource.Id, get the rows where the ApproverId is not the one that is passed. Can I combine it all in a single query instead of using temp tables?
Thanks!
Edit: I'm using SQL Server 2008 R2.
Edit 2: Here's my stored procedure. I have changed the logic slightly after reading the comments. Can we get rid of all temp tables and make it faster -
ALTER PROCEDURE GetResourceDataByApprover
#ApproverId UNIQUEIDENTIFIER
AS
CREATE TABLE #Table1
(
Id SMALLINT PRIMARY KEY
IDENTITY(1, 1) ,
ResourceId UNIQUEIDENTIFIER
)
CREATE TABLE #Table2
(
ResourceId UNIQUEIDENTIFIER ,
ProjectId UNIQUEIDENTIFIER ,
ProjectName NVARCHAR(1024)
)
INSERT INTO #Table1
SELECT DISTINCT
ResourceId
FROM dbo.Resource T
WHERE T.ApproverId = #ApproverId
DECLARE #i INT
DECLARE #numrows INT
DECLARE #resourceId UNIQUEIDENTIFIER
SET #i = 1
SET #numrows = ( SELECT COUNT(*)
FROM #Table1
)
IF #numrows > 0
WHILE ( #i <= ( SELECT MAX(Id)
FROM #Table1
) )
BEGIN
SET #resourceId = ( SELECT ResourceId
FROM #Table1
WHERE Id = #i
)
INSERT INTO #Table2
SELECT
T.ResourceId ,
T.ProjectId ,
P.Name AS ProjectName
FROM dbo.[Resource] T
INNER JOIN dbo.Project P ON T.ProjectId = P.ProjectId
WHERE T.ResourceId = #resourceId
SET #i = #i + 1
END
SELECT *
FROM #Table1
SELECT *
FROM #Table2
DROP TABLE #Table1
DROP TABLE #Table2

This query should return two rows for every resource, one for the specified approver and one for all other approvers.
SELECT
Id,
CASE
WHEN ApproverId=#approverId THEN 'SpecifiedApprover'
ELSE 'OtherApprover'
END AS Approver,
SUM(Hours) AS Hours
FROM Resource
GROUP BY
Id,
CASE
WHEN ApproverId=#approverId THEN 'SpecifiedApprover'
ELSE 'OtherApprover'
END

Do you want to know how concrete Approver wastes his time?
SELECT p.Id, p.Name, SUM(r.Hours) as TotalHours
FROM Resource r
LEFT JOIN Project p
ON r.ProjectId = p.Id
WHERE ApproverId = %ConcreteApproverId%
GROUP BY p.Id, p.Name
HAVING SUM(r.Hours) > 0
This query will produce this table example:
+-----+----------+-------+
| Id | Project | Hours |
+-----+----------+-------+
| 203 | ProjectA | 25 |
| 202 | ProjectB | 34 |
| 200 | ProjectC | 46 |
+-----+----------+-------+

Related

Sql how to convert nest while loops to a CTE using two temp tables

I have one temp table that pulls from the Abstracting table for dx codes and Registration table for the account number. It joins by the VisitID and the dx codes are in order by DiagnosisUrn - #Visits
I need to join it to the DiagTable. The dx codesin this table are the primary ones for billing, in
order by Transaction Number ID with the lowest number being the most primary.
In the end, for each visit id , account id, I need to for the Dx codes to print out
like this example:
Account ICD10 SequenceNumber
AT000118 R06.00 1
AT000118 I25.10 2
AT000118 I65.23 3
AT000118 E11.29 4
AT000118 Z95.1 5
AT000118 E11.65 6
AT000118 E78.2 7
AT000118 E78.1 8
AT000118 E11.42 9
For this particular account (there are many others similar), all of the dx are in the Visit table
however only the first four are in Diag table with the proper TransactionDiagnosisURN/DiagnosisURN/Sequence Number
The While loops reorder the rest of DX codes that were in the visit temp table and adding them to the end of the ones in the Diag table with the result populating the PBDxCodes temp table.
It needs to run by date range - I've changed it to pull a few account numbers instead to try to work on
a CTE. Using loops causes it to run an extremely long time and sometimes it just times out.
I'm getting a recursion error when trying to convert the query to CTE. I have only used basic CTE in the past and it has been a while.
Below is the query using the while loop and then my attempt at trying to convert one loop to a CTE:
While loops:
DECLARE #NumofVisits AS INT
DECLARE #NumberofTxs AS INT
DECLARE #Looper AS INT
DECLARE #ThisVisitID AS VARCHAR(35)
--Get the VisitIDs to find Dx Codes
DROP TABLE IF EXISTS #Visits
SELECT DISTINCT
RAM.VisitID
,RAM.AccountNumber
,ADX.DiagnosisCode_MisDxID
,CAST(ADX.DiagnosisUrnID AS INT) AS ABSDxCode
INTO #Visits
FROM livefdb.dbo.AbsAcct_Diagnoses ADX
JOIN livefdb.dbo.RegAcct_Main AS RAM
ON RAM.VisitID = ADX.VisitID
AND RAM.SourceID = ADX.SourceID
AND RAM.Facility_MisFacID NOT IN ('KK', 'JFJ','MPM')
AND RAM.RegistrationType_MisRegTypeID IN ('AMB','AMBR','BNV')
LEFT JOIN livefdb.dbo.HimRec_Main AS HRM
ON HRM.SourceID = RAM.SourceID
AND HRM.PatientID = RAM.PatientID
WHERE ADX.VisitID IN ('LE1-B20210114114749175', 'AT0-B20191211155403251'
,'ID0-B20201201104450465','OM1-B20210107093907435'
,'AT0-B20191205154143298','LE0-B20200716135146384'
,'PC1-B20210111125154209','SV1-B20210112122435108'
,'UB0-B20200915140417079','ID1-B20201222150226545'
)
SET #NumofVisits = (SELECT COUNT(DISTINCT VisitID) FROM #Visits )
-- Create a table to hold Dx data for each visit
DROP TABLE IF EXISTS #PBDxCodes
CREATE TABLE #PBDxCodes (
EncounterRecordNumber VARCHAR(18),
ICD10DiagnosisCode VARCHAR(15),
SequenceNumber INT,
)
-- Get the Diagnosis from BAR Transactions. The least transaction number is the Primary Charge
-- and the Diagnosis Codes are the Primary Diagnosis codes
WHILE #NumofVisits > 0
BEGIN
DROP TABLE IF EXISTS #UpdateDiag
CREATE TABLE #UpdateDiag (
DiagnosisUrnID INT IDENTITY(1,1) PRIMARY KEY,
VisitID VARCHAR(35),
Diagnosis_MisDxID VARCHAR(50)
)
SET #ThisVisitID = (SELECT TOP 1 VisitID FROM #Visits)
SELECT DISTINCT
BATD.VisitID,
BATD.TransactionNumberID,
CAST(BATD.TransactionDiagnosisUrnID AS INT) AS TransactionDiagnosisUrnID,
BATD.TransactionDiagnosis_MisDxID
INTO #Diag
FROM livefdb.dbo.BarAcct_TxnDiagnoses AS BATD
WHERE BATD.VisitID = #ThisVisitID
SET #NumberofTxs = (SELECT COUNT(DISTINCT TransactionNumberID) FROM #Diag)
SET #Looper = 0
WHILE ( #NumberofTxs > #Looper)
BEGIN
INSERT INTO #UpdateDiag(VisitID, Diagnosis_MisDxID)
SELECT
VisitID,
TransactionDiagnosis_MisDxID
FROM #Diag
WHERE TransactionNumberID =
(CASE WHEN 1 = (SELECT COUNT(DISTINCT TransactionNumberID) FROM #Diag)
THEN (SELECT TOP 1 TransactionNumberID FROM #Diag )
ELSE (SELECT MIN(TransactionNumberID) FROM #Diag)
END)
AND TransactionDiagnosis_MisDxID NOT IN (SELECT Diagnosis_MisDxID FROM #UpdateDiag)
ORDER BY TransactionDiagnosisUrnID
DELETE FROM #Diag WHERE TransactionNumberID = (SELECT MIN(TransactionNumberID) FROM #Diag)
SET #Looper = #Looper + 1
END
-- Are there Diagnosis in Abstracting that are not in BAR
INSERT INTO #UpdateDiag(VisitID, Diagnosis_MisDxID)
SELECT
VisitID,
DiagnosisCode_MisDxID
FROM #Visits
WHERE #Visits.VisitID = #ThisVisitID
AND #Visits.DiagnosisCode_MisDxID NOT IN (SELECT Diagnosis_MisDxID FROM #UpdateDiag)
ORDER BY #Visits.ABSDxCode
-- Add this visit to the temp table holding final results
INSERT INTO #PBDxCodes (EncounterRecordNumber,SequenceNumber,ICD10DiagnosisCode,SourceSystem)
SELECT DISTINCT
#Visits.AccountNumber AS EncounterRecordNumber,
#UpdateDiag.DiagnosisUrnID AS SequenceNumber,
#UpdateDiag.Diagnosis_MisDxID AS ICD10DiagnosisCode
FROM #UpdateDiag
INNER JOIN #Visits ON #UpdateDiag.VisitID = #Visits.VisitID
DELETE FROM #Visits WHERE VisitID = #ThisVisitID
SET #NumofVisits = #NumofVisits - 1
DROP TABLE #Diag, #UpdateDiag
END
SELECT * FROM #PBDxCodes
WHERE EncounterRecordNumber='AT0001184503'
ORDER BY EncounterRecordNumber, SequenceNumber
DROP TABLE #Visits, #PBDxCodes
CTE Attempt:
DECLARE #NumofVisits AS INT
DECLARE #NumberofTxs AS INT
DECLARE #Looper AS INT
DECLARE #ThisVisitID AS VARCHAR(35)
--Get VisitID,Account Nos and Dx in Abstracting.
DROP TABLE IF EXISTS #Visits
SELECT DISTINCT
RAM.VisitID
,RAM.AccountNumber
,ADX.DiagnosisCode_MisDxID
,CAST(ADX.DiagnosisUrnID AS INT) AS ABSDxCode
INTO #Visits
FROM livefdb.dbo.AbsAcct_Diagnoses ADX
JOIN livefdb.dbo.RegAcct_Main RAM
ON ADX.SourceID=RAM.SourceID
AND ADX.VisitID=RAM.VisitID
AND RAM.Facility_MisFacID NOT IN ('KK', 'JFJ','MPM')
AND RAM.RegistrationType_MisRegTypeID IN ('AMB','AMBR','BNV')
WHERE ADX.VisitID IN ('AT0-B20191211155403251','LE1-B20210114114749175')
SET #NumofVisits = (SELECT COUNT(DISTINCT VisitID) FROM #Visits);
WITH CTE AS (
SELECT
V.ABSDxCode
,#NumofVisits AS n
,V.VisitID
,V.DiagnosisCode_MisDxID
FROM #Visits V
UNION ALL
SELECT
C.ABSDxCode
,C.n+1
,V.VisitID AS VisitID
,V.DiagnosisCode_MisDxID
FROM CTE C
INNER JOIN #Visits AS V ON V.VisitID=C.VisitID
)
SELECT C.ABSDxCode, C.DiagnosisCode_MisDxID
FROM CTE C
WHERE C.n=(SELECT MAX(n) FROM CTE WHERE ABSDxCode=C.ABSDxCode)

SQL - get all parents/childs?

hopefully someone can help with this. I have recieved a table of data which I need to restructure and build a Denorm table out of. The table structure is as follows
UserID Logon ParentID
2344 Test1 2000
2345 Test2 2000
The issue I have is the ParentID is also a UserID of its own and in the same table.
SELECT * FROM tbl where ParentID=2000 gives the below output
UserID Logon ParentID
2000 Test Team 2500
Again, the ParentID of this is also stored as a UserID..
SELECT * FROM tbl where ParentID=2500 gives the below output
UserID Logon ParentID
2500 Test Division NULL
I want a query that will pull all of these relationships and the logons into one row, with my output looking like the below.
UserID Username Parent1 Parent2 Parent3 Parent4
2344 Test1 Test Team Test Division NULL NULL
2345 Test2 Test Team Test Division NULL NULL
The maximum number of parents a user can have is 4, in this case there is only 2. Can someone help me with the query needed to build this?
Appreciate any help
Thanks
Jess
You can use basicly LEFT JOIN. If you have static 4 parent it should work. If you have unknown parents you should do dynamic query.
SELECT U1.UserId
,U1.UserName
,U2.UserName AS Parent1
,U3.UserName AS Parent2
,U4.UserName AS Parent3
,U5.UserName AS Parent4
FROM Users U1
LEFT JOIN Users U2 ON U1.ParentId = U2.UserId
LEFT JOIN Users U3 ON U2.ParentId = U3.UserId
LEFT JOIN Users U4 ON U3.ParentId = U4.UserId
LEFT JOIN Users U5 ON U4.ParentId = U5.UserId
EDIT : Additional(to exclude parent users from the list) :
WHERE NOT EXISTS (SELECT 1 FROM Users UC WHERE U1.UserId = UC.ParentId)
select
tb1.UserId as UserId,
tb1.UserName as UserName,
tb2.UserName as Parent1,
tb3.UserName as Parent2,
tb4.UserName as Parent3,
tb5.UserName as Parent4
from tbl t1
left join tbl t2 on t2.UserId=t1.ParentID
left join tbl t3 on t3.UserId=t2.ParentID
left join tbl t4 on t4.UserId=t3.ParentID
left join tbl t5 on t5.UserId=t4.ParentID;
you need to do 4 left joins in order to fetch 4 parent details
Use a recursive CTE to get the levels then pivot to put them in columns:
WITH cte(UserID, Logon, ParentID, ParentLogon, ParentLevel) AS
(
SELECT UserID, Logon, ParentID, Logon, 0
FROM users
UNION ALL
SELECT u.UserID, u.Logon, u.ParentID, cte.ParentLogon, ParentLevel + 1
FROM users u
JOIN cte ON cte.UserID = u.ParentID
)
SELECT UserId, Logon, Parent1, Parent2, Parent3, Parent4 FROM cte
PIVOT (
MAX(ParentLogon)
FOR ParentLevel
IN (
1 AS Parent1,
2 AS Parent2,
3 AS Parent3,
4 AS Parent4
)
)
See SQL Fiddle example
In order to get all parent or child, it's efficient to use a recursive function which would fetch the whole hierarchy.
Sample Table:
CREATE TABLE #TEST
(
[Name] varchar(100),
ManagerName Varchar(100),
Number int
)
Insert some values
Insert into Test values
('a','b'), ('b','c'), ('c','d'), ('d','e'), ('e','f'), ('f','g')
Create recursive function as below
CREATE FUNCTION [dbo].[fnRecursive] (#EmpName Varchar(100), #incremental int)
RETURNS #ret TABLE
(
ManagerName varchar(100),
Number int
)
AS
BEGIN
Declare #MgrName varchar(100)
SET #MgrName = (Select ManagerName from test where [name] = #EmpName)
Insert into #ret values (#MgrName, #incremental)
if(#MgrName is not null)
BEGIN
SET #incremental = #incremental + 1;
Insert into #ret
Select ManagerName, Number from [fnRecursive](#MgrName, #incremental)
END
RETURN;
END
If this function is joined with table, it should list the hierarchy for all employees
CREATE TABLE #TEST
(
[Name] varchar(100),
ManagerName Varchar(100),
Number int
)
Insert into #TEST
Select x.[Name], x.ManagerName,x.number from (
select t.[Name],a.ManagerName as managerName, a.number as number from TEST t outer apply
(
select * from [fnRecursive](t.[Name],1)
) a)
x
Select * from #Test
If we do a pivot on the table (excluding the 'Number' column). Assuming we store in the table "#temp" it should list all the managers as a column.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[ManagerName] )
FROM #temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'select * from #temp
pivot
(
min([managername])
for managername in (' + #cols + ')
) p '
execute(#query)
But this doesn't name the column as 'Parent1', 'Parent2' instead with the dynamic column name.
Link below should help to set custom column name for the dynamic pivot table
https://stackoverflow.com/questions/16614994/sql-server-pivot-with-custom-column-names

SQL Server : searching value doesn't have entry in table

I have a table which has the following values:
ID | Name
---------------
1 | Anavaras
2 | Lamurep
I need a query which outputs the value which doesn't have entry in the table.
For e.g:
If my where clause contains id in('1','2','3','4'), should produce output has
3 |
4 |
for the above entries in the table.
You would put this into a "derived table" and use left join or a similar construct:
select v.id
from (values(1), (2), (3), (4)) v(id) left join
t
on t.id = v.id
where t.id is null;
Something like this:
"SELECT id FROM table WHERE name IS NULL"
I'd assume?
First you need to split your in to a table. Sample split function is here:
CREATE FUNCTION [dbo].[split]
(
#str varchar(max),
#sep char
)
RETURNS
#ids TABLE
(
id varchar(20)
)
AS
BEGIN
declare #pos int,#id varchar(20)
while len(#str)>0
begin
select #pos = charindex(#sep,#str + #sep)
select #id = LEFT(#str,#pos),#str = SUBSTRING(#str,#pos+1,10000000)
insert #ids(id) values(#id)
end
RETURN
END
Then you can use this function.
select id from dbo.split('1,2,3,4,5',',') ids
left join myTable t on t.id=ids.id
where t.id is null
-- if table ID is varchar then '''1'',''2'',''3'''

TSQL Multiple count using same table with different JOIN

I have a weird situation and not too sure how to approach it.
I have 2 separate tables:
Table A is submissions
id
submitterQID
nomineeQID
story
Table B is employees
QID
Name
Department
I am trying to get the total number of submissions grouped by department as well as the total number of nominations.
This is what my Stored procedure looks like:
BEGIN
SELECT TOP 50 count(A.[nomineeQID]) AS totalNominations,
count(A.[subQID]) AS totalSubmissions,
B.[DepartmentDesc] AS department
FROM empowermentSubmissions AS A
JOIN empTable AS B
ON B.[qid] = A.[nomineeQID]
WHERE A.[statusID] = 3
AND A.[locationID] = #locale
GROUP BY B.[Department]
ORDER BY totalNominations DESC
FOR XML PATH ('data'), TYPE, ELEMENTS, ROOT ('root');
END
This issue with this is that the JOIN is joining by the nomineeQID only and not the subQID as well.
My end result I am looking for is:
Department Customer Service has 25 submissions and 90 nominations
ORDERED BY the SUM of both counts...
I tried to just JOIN again on the subQID but was told I cant join on the same table twice.
Is there an easier way to accomplish this?
This is a situaton where you'll need to gather your counts independently of each other. Using two left joins will cause some rows to be counted twice in the first left join when the join condition is met for both. Your scenario can be solved using either correlated subqueries or an outer apply gathering the counts on different criteria. I did not present a COUNT(CASE ... ) option here, because you don't have an either-or scenario in the data, you have two foreign keys to the employees table. So, setting up sample data:
declare #empowermentSubmissions table (submissionID int primary key identity(1,1), submissionDate datetime, nomineeQID INT, submitterQID INT, statusID INT, locationID INT)
declare #empTable table (QID int primary key identity(1,1), AreaDesc varchar(10), DepartmentDesc varchar(20))
declare #locale INT = 0
declare #n int = 1
while #n < 50
begin
insert into #empTable (AreaDesc, DepartmentDesc) values ('Area ' + cast((#n % 2)+1 as varchar(1)), 'Department ' + cast((#n % 4)+1 as varchar(1)))
set #n = #n + 1
end
set #n = 1
while #n < 500
begin
insert into #empowermentSubmissions (submissionDate, nomineeQID, submitterQID, StatusID, locationID) values (dateadd(dd,-(cast(rand()*600 as int)),getdate()), (select top 1 QID from #empTable order by newid()), (select top 1 QID from #empTable order by newid()), 3 + (#n % 2) - (#n % 3), (#n % 2) )
set #n = #n + 1
end
And now the OUTER APPLY option:
SELECT TOP 50 E.DepartmentDesc, SUM(N.Nominations) Nominations, SUM(S.TotalSubmissions) TotalSubmissions
FROM #empTable E
OUTER APPLY (
SELECT COUNT(submissionID) Nominations
FROM #empowermentSubmissions A
WHERE A.statusID = 3
AND A.nomineeQID = E.QID
AND A.locationID = #locale
) N
OUTER APPLY (
SELECT COUNT(submissionID) TotalSubmissions
FROM #empowermentSubmissions A
WHERE A.statusID = 3
AND A.submitterQID = E.QID
AND A.locationID = #locale
) S
GROUP BY E.DepartmentDesc
ORDER BY SUM(Nominations) + SUM(TotalSubmissions) DESC

Is it possible to group unlike items and count them together?

Given the following table:
Chain Name
123 Company 1
124 Other Company 1
123 Whatever Company
125 This One
126 That One
125 Another One
127 Last One
I get the following results when I do a Count on the Chain column:
123 2
124 1
125 2
126 1
127 1
Is it possible to group Chain 123 and 124 so they're counted together? Also group 125 and 126? The modified results would look like this:
123/124 3
125/126 3
127 1
My SQL looks like this:
SELECT Table1.Chain, Count(*) as [Count]
FROM Table1 LEFT JOIN Table2 on Table1.Chain = Table2.Chain
WHERE (((Table1.Chain) IN (Table2.Chain)))
GROUP BY Table1.Chain
ORDER BY Table1.Chain;
Thank you!
Depending upon your needs, this might be a bit of a hack, but I would probably add a table to store the Chain and ChainGroup that you are seeking. Something like this:
Chain ChainGroup
123 123/124
124 123/124
125 125/126
126 125/126
127 127/128
Then, in the query, I would join to this table and instead of grouping by Chain I would group by ChainGroup.
I would prefer this over something like a nested IIF statement as those get pretty difficult to debug, and odds are you'll have additional groupings in the future which would be trivial to add to the table and have the new grouping automatically appear in the query.
yes, you can:
SELECT min(Table1.Chain) & '/' & max(Table1.Chain) as chain, Count(*) as [Count]
FROM Table1 LEFT JOIN Table2 on Table1.Chain = Table2.Chain
WHERE (((Table1.Chain) IN (Table2.Chain)))
GROUP BY int((Table1.Chain-1)/2)
ORDER BY min(Table1.Chain);
You can use a nested Iif statement. Hopefully I've got all my parentheses right below! :-)
SELECT Iif(Table1.Chain="123", "123/124",
Iif(Table1.Chain="124", "123/124",
Iif(Table1.Chain="125", "125/126",
Iif(Table1.Chain="126", "125/126", Table1.Chain)))) as [Chain]
, Count(*) as [Count]
FROM Table1 LEFT JOIN Table2 on Table1.Chain = Table2.Chain
WHERE (((Table1.Chain) IN (Table2.Chain)))
GROUP BY Iif(Table1.Chain="123", "123/124",
Iif(Table1.Chain="124", "123/124",
Iif(Table1.Chain="125", "125/126",
Iif(Table1.Chain="126", "125/126", Table1.Chain))))
ORDER BY Table1.Chain;
You could also move the case statement into a subquery in your from clause or a common table expression if you don't want to write it twice in your query.
consider something like:
SELECT
chain_group, COUNT(*) FROM (
SELECT
Table1.Chain,
switch(Table1.Chain IN("123","124"), "123/124",
Table1.Chain IN("125","126"),"125/126",
Table1.Chain) AS chain_group
FROM
Table1 INNER JOIN
Table2 ON
Table1.Chain = Table2.Chain) t
GROUP BY chain_group
ORDER BY chain_group
You can see the below example
----- Make main Table
CREATE TABLE #test
( id int , Name varchar(100))
INSERT #test(id,Name)
values (123,'Company 1'),
(124,'Other Company 1'),
(123, 'Whatever Company'),
(125, 'This One'),
(126 , 'That One'),
(125, 'Another One'),
(127, 'Last One')
CREATE TABLE #temp
(rowID INT IDENTITY(1,1) , ID INT ,cnt INT )
CREATE TABLE #tempResult
(ID VARCHAR(20) ,cnt INT )
INSERT INTO #temp(ID,cnt)
SELECT ID ,COUNT(1) cnt FROM #test GROUP BY ID
DECLARE #rowCnt INT , #TotalCnt INT , #even INT , #odd INT ,
#idNum VARCHAR(20) , #valueCnt INT , #inStart INT = 1
SET #rowCnt = 1
SET #even = 1
SET #odd = 2
SELECT #TotalCnt = COUNT(1) FROM #temp
WHILE #rowCnt <= #TotalCnt
BEGIN
SET #inStart = 1
SET #odd = #rowCnt
SET #even = #rowCnt + 1
SET #idNum = ''
SET #valueCnt = 0
WHILE #inStart <= 2
BEGIN
IF #inStart = 1
Begin
SELECT #idNum = Convert(VARCHAR(5),ID) , #valueCnt = cnt
FROM #temp WHERE rowID = #odd
End
ELSE
BEGIN
SELECT #idNum = #idNum + '/' + Convert(VARCHAR(5),ID) , #valueCnt = #valueCnt + cnt
FROM #temp WHERE rowID = #even
END
SET #inStart = #inStart + 1
END
INSERT INTO #tempResult (ID, Cnt)
VALUES (#idNum,#valueCnt)
SET #rowCnt = #rowCnt + 2
END
SELECT *
FROM #tempResult