How do I modify this T-SQL query so that its ouput can be joined with a table in my database? - sql

I am using SQl Server 2014. I have the following T-SQL query (with its corresponding output given below):
USE mydatabase
declare #t table (StayID int)
insert into #t select distinct StayID from DateOfBirth
while ((select count(1) from #t) > 0)
begin
declare #Id int = (select top 1 StayID from #t)
declare #age_tab table (StayID int, Age int, Year1 date)
declare #cage1 smallint = 2, #cage2 smallint = 5
declare #i_a int = (select AdultCount from DateOfBirth where StayID = #Id)
declare #i_c1 int = (select [0-3] from DateOfBirth where StayID = #Id)
declare #i_c2 int = (select [4-6] from DateOfBirth where StayID = #Id)
declare #age int = (select Age from DateOfBirth where StayID = #Id)
declare #Year1 date = (select cast(datepart(year,ArrivalDate) as varchar) from DateOfBirth where StayID = #Id)
while (#i_a>1)
begin
insert into #age_tab select #Id, (#age + 2), #Year1
set #age-=2
set #i_a-=1
end
while (#i_c1>0)
begin
insert into #age_tab select #Id, #cage1, #Year1
set #i_c1-=1
end
while (#i_c2>0)
begin
insert into #age_tab select #Id, #cage2, #Year1
set #i_c2-=1
end
insert into #age_tab select StayID, Age, cast(datepart(year,ArrivalDate) as varchar) from DateOfBirth where StayID = #Id
delete #t where StayID = #Id
end
select * from #age_tab
order by StayID, Age desc
The output of the above query is as follows:
StayID Age Year1
101 54 2016-01-01
101 52 2016-01-01
102 42 2016-01-01
102 40 2016-01-01
102 14 2016-01-01
...
I want to join the output of this query with values from another table in my database. Given the above query uses temporary tables to perform its operation, I am unable to wrap it into a CTE.
The additional information I want to bring to my output is stored in, say, table "t2".
Let's say the output from the query above is temporarily stored in a table called "t1"
So, I want to do something like this:
Select a.*
, b.Cty
from t1 a
LEFT JOIN t2 b on b.StayID = a.StayID
How can I do this?

Related

Concate string into temp table in cursor

I have a temp table structure #temp2 like this
route total driverID
------------------------
10B 300
7B 400
and would like to add the driverID column with a result like 5555, 68989
to do this, I use the cursor to loop another table look like this
driverID routeNo
-------------------
5555 10B
68989 10B
72000 7B
Here is the code
declare #driverID varchar(max)
declare #routeNew varchar(20)
DECLARE brand_cursor CURSOR FOR
select distinct driver_id, route_number from [dbcwl].[dbo].[collection_deduction_summary]
where YEAR(trans_date) = #year
and MONTH(trans_date) = #month
and route_number in (select actual_route from [dbcwl].[dbo].[livedispatchingdata_pmhs_daily_summary] where status = 'OK' and YEAR(trans_date) = #year AND month(trans_date) = #month )
and vehicle_id in (select vehicle_id from [dbcwl].[dbo].[livedispatchingdata_pmhs_daily_summary] where status = 'OK' and YEAR(trans_date) = #year AND month(trans_date) = #month )
group by route_number, driver_id
OPEN brand_cursor
FETCH NEXT FROM brand_cursor
INTO #driverID, #routeNew
WHILE ##FETCH_STATUS = 0
BEGIN
--update #temp2
update #temp2 set driverID += ','+ #driverID where routeNo = #routeNew;
FETCH NEXT FROM brand_cursor
INTO #driverID, #routeNew
END
CLOSE brand_cursor;
DEALLOCATE brand_cursor;
sadly, I got the driverID column is null
and would like to have finalized temp table look like this:
route total driverID
------------------------
10B 300 5555,68989
7B 400 72000
;with cte as -- Step 1: Get all Driver Ids by routeNo
(
SELECT routeNo, driverID =
STUFF((SELECT DISTINCT ', ' + CAST(driverID AS NVARCHAR(100))
FROM #A b
WHERE b.routeNo = a.routeNo
FOR XML PATH('')), 1, 2, '')
FROM #A a
GROUP BY routeNo
)
update b -- Step 2: Update driverID accordingly.
set driverID = cte.driverID
from #B b
inner join cte on b.route = cte.routeNo
Result here
You can string_agg():
update t
set t.driverID = ot.drivers
from #temp2 t join
(select ot.routeNo, string_agg(driverID, ',') as drivers
from othertable ot
group by ot.routeNo
) ot
on t.routeNo = ot.routeNo;

dynamic alias in sql server

I want query field with different alias in stored procedure
select COUNT(EmpCode) as CountEmp+#para
result shoud be
CountEmp1
45
CountEmp2
54
CountEmp1
76
Query loop in c# code:
select COUNT(EmpCode) where something = #something as CountEmp+#para
Approach without dynamic SQL:
--I create temp table for demonstration
DECLARE #some_table TABLE (
Something int,
EmpCode INT
)
INSERT INTO #some_table (Something, EmpCode)
VALUES (1, 10),(1, 22),(1, 12),(2, 12),(2, 30),(3, 65),(3, 15),(3, 11),(3, 5)
--Declare parameter we want to search
DECLARE #param int = 1
--Query
--In cte we select what we need based on parameter
;WITH cte AS (
SELECT 'CountEmp'+CAST(#param as nvarchar(10)) as SomeThing,
CAST(COUNT(EmpCode) as nvarchar(10)) as EmpCodeCount,
ROW_NUMBER() OVER (ORDER BY SomeThing ) as rn
FROM #some_table
WHERE SomeThing = #param
GROUP BY SomeThing
)
--And here comes UNION
SELECT SomeThing as Result
FROM (
SELECT SomeThing,rn
FROM cte
UNION ALL
SELECT EmpCodeCount ,rn
FROM cte
) as t
ORDER BY rn, SomeThing DESC
Output:
Result
------------------
CountEmp1
3
(2 row(s) affected)
Please try to make use of below code. Its working fine with SQL Server 2012.
IF OBJECT_ID ('temp..#Mytable') IS NOT NULL
CREATE TABLE #Mytable (ID INT IDENTITY (1,1),EmpCode INT)
DECLARE #max int ,#count int
SET #max =0;
DECLARE #str varchar(10)
INSERT #Mytable
(EmpCode)
VALUES
(10),
(45),
(35),
(63),
(56),
(65)
SET #count = (SELECT COUNT (ID) FROM #Mytable )
WHILE #count > #max
BEGIN
SET #max = #max+1
SET #str = CONVERT(varchar(10),#max)
EXEC('SELECT EmpCode AS Empcode'+#str+ ' FROM #Mytable WHERE ID = '+#str)
END

Replace Cursor Next number assignment Operation with Set based equivalent

Good day all,
I have the following cursor query and would like to replace it with a set based query to address performance issues.
DECLARE #EmpIDM CHAR(21);
DECLARE #EmpName CHAR(21);
DECLARE #EMPCatID INT;
DECLARE Assign_Emp SCROLL CURSOR
FOR
SELECT DISTINCT EMP
, EMPNAME
FROM HR_EMPLOYEES
SET NOCOUNT ON
OPEN Assign_Emp;
FETCH NEXT
FROM Assign_Emp
INTO #EmpIDM
, #EmpName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #EMPCatID = (
SELECT TOP 1 CategoryID
FROM Categories
)
UPDATE Categories
SET CategoryID = (CategoryID + 1) /*Increment Category ID for next Insert*/
INSERT INTO Table1 (
EmpNumber
, EmployeeName
, EmployeeCategoryID
)
VALUES (
#EmpIDM
, #EmpName
, #EMPCatID
)
FETCH NEXT
FROM Assign_Emp
INTO #EmpIDM
, #EmpName
END
CLOSE Assign_Emp;
CLOSE Assign_Emp;
SET NOCOUNT OFF
My challenge is adapting the following code segment into a set based operation
SET #EMPCatID = (
SELECT TOP 1 CategoryID
FROM Categories
)
UPDATE Categories
SET CategoryID = (CategoryID + 1) /*Increment Category ID for next Insert*/
I humbly appreciate any insight on how I can achieve this.
Many Thanks,
Re-write using temp. table with identity column:
declare #offset int
select #offset = isnull(max(CategoryID),0) from Categories
create table #data (
EmpNumber CHAR(21),
EmployeeName CHAR(21),
EmployeeCategoryID int identity
)
INSERT INTO #data (
EmpNumber
, EmployeeName)
SELECT DISTINCT EmpIDM
, EmpName
FROM HR_EMPLOYEES
insert into Table1 (
EmpNumber
, EmployeeName
, EmployeeCategoryID
) select
EmpNumber
, EmployeeName
, EmployeeCategoryID + #offset
from #data
update Categories
set CategoryID = (select max(EmployeeCategoryID) from #data) + #offset

Group multiple result set by count

I have a query which loops over some data and returns a count if true. However because of the loop the count only counts that result, so you just get 1,1,1,1 returned etc.. rather than 4.
WHILE (#I <= #RowCount)
BEGIN
DECLARE #forename VARCHAR(50)
DECLARE #surname VARCHAR(50)
SELECT #DOB = forename FROM #mytemp WHERE row = #I
SELECT #forename = forename FROM #mytemp WHERE row = #I + 1
SELECT #surname = forename FROM #mytemp WHERE row = #I + 2
SELECT COUNT(*) FROM [FPTDB].dbo.clients WHERE forename = #forename AND surname = #surname AND dob = #DOB
SET #I = #I + 3
END
I presume i need to group the result set somehow to count the results, but i'm not sure how.
I suggest skip WHILE and you can do like this (last select is not tested):
DECLARE #mytemp TABLE (forename VARCHAR(100))
INSERT INTO #mytemp SELECT 'tom'
INSERT INTO #mytemp SELECT 'bob'
INSERT INTO #mytemp SELECT 'smith'
INSERT INTO #mytemp SELECT 'mary'
INSERT INTO #mytemp SELECT 'tedy'
INSERT INTO #mytemp SELECT 'carry'
INSERT INTO #mytemp SELECT 'wmary'
INSERT INTO #mytemp SELECT 'wtedy'
INSERT INTO #mytemp SELECT 'wcarry'
--ADD surname, forename and DOB numbering to table (column isType)
;WITH mytemp AS (
SELECT forename, ROW_NUMBER() OVER (ORDER BY forename) as ID
FROM #mytemp
)
SELECT forename,
CASE
WHEN ID % 3 = 0 THEN 3 --surname
WHEN ID % 3 = 2 THEN 2 --forename
ELSE 1 -- DOB
END AS isType
INTO #myTemp2
FROM mytemp
ORDER BY ID
/*result like this
forename ID isType
bob 1 1
carry 2 2
mary 3 3
smith 4 1
tedy 5 2
tom 6 3
wcarry 7 1
wmary 8 2
wtedy 9 3
*/
--Join just created table 3 times
SELECT COUNT(*)
FROM [FPTDB].dbo.clients AS C
INNER JOIN #myTemp2 AS T1 --DOB
ON T1.forename= C.dob
AND T1.isType = 1
INNER JOIN #myTemp2 AS T2 --forename
ON T2.forename = C.forename
AND T2.isType = 2
INNER JOIN #myTemp2 AS T3 --surname
ON T3.forename= C.surname
AND T3.isType = 3
You should add another variable and store the sum of every loop count in it.
After the loop you can output the variable value.
DECLARE #tot INT unsigned
SELECT #tot = 0
WHILE (#I <= #RowCount)
BEGIN
DECLARE #forename VARCHAR(50)
DECLARE #surname VARCHAR(50)
SELECT #DOB = forename FROM #mytemp WHERE row = #I
SELECT #forename = forename FROM #mytemp WHERE row = #I + 1
SELECT #surname = forename FROM #mytemp WHERE row = #I + 2
SELECT #tot = #tot + COUNT(*) FROM [FPTDB].dbo.clients WHERE forename = #forename AND surname = #surname AND dob = #DOB
SET #I = #I + 3
END
SELECT #tot

Loop through a recordset and use the result to do another SQL select and return the results

I am completely new to stored procedure. This time, I need to create a stored procedure in MS SQL.
Let's say I have the following table.
Table name: ListOfProducts
--------------------------
SomeID, ProductID
34, 4
35, 8
35, 11
How do I pass in a SomeID. Use this SomeID to select a recordset from table, ListOfProducts. Then loop through this record set.
Let's say I pass in SomeID = 35.
So, the record set will return 2 records with SomeID 35. In the loop, I will get ProductID 8 and 11, which will be used to do another select from another table.
The stored procedure should return the results from the 2nd select.
How can I do this in MS SQL stored procedure?
Sorry, for this newbie question. Thanks for any help.
If you want looping through the records. You can do like:
--Container to Insert Id which are to be iterated
Declare #temp1 Table
(
tempId int
)
--Container to Insert records in the inner select for final output
Declare #FinalTable Table
(
Id int,
ProductId int
)
Insert into #temp1
Select Distinct SomeId From YourTable
-- Keep track of #temp1 record processing
Declare #Id int
While((Select Count(*) From #temp1)>0)
Begin
Set #Id=(Select Top 1 tempId From #temp1)
Insert Into #FinalTable
Select SomeId,ProductId From ListOfProducts Where Id=#Id
Delete #temp1 Where tempId=#Id
End
Select * From #FinalTable
There is probably no point in writing an explicit loop if you don't need to preform some action on the products that can't be done on the whole set. SQL Server can handle stuff like this much better on its own. I don't know what your tables look like, but you should try something that looks more like this.
CREATE PROC dbo.yourProcName
#SomeID int
AS
BEGIN
SELECT
P.ProductId,
P.ProductName
FROM
Product P
JOIN
ListOfProducts LOP
ON LOP.ProductId = P.ProductId
WHERE
LOP.SomeId = #SomeID
END
I had to do something similar in order to extract hours from a select resultset start/end times and then create a new table iterating each hour.
DECLARE #tCalendar TABLE
(
RequestedFor VARCHAR(50),
MeetingType VARCHAR(50),
RoomName VARCHAR(MAX),
StartTime DATETIME,
EndTime DATETIME
)
INSERT INTO #tCalendar(RequestedFor,MeetingType,RoomName,StartTime,EndTime)
SELECT req as requestedfor
,meet as meetingtype
,room as rooms
,start as starttime
,end as endtime
--,u.datetime2 as endtime
FROM mytable
DECLARE #tCalendarHours TABLE
(
RequestedFor VARCHAR(50),
MeetingType VARCHAR(50),
RoomName VARCHAR(50),
Hour INT
)
DECLARE #StartHour INT,#EndHour INT, #StartTime DATETIME, #EndTime DATETIME
WHILE ((SELECT COUNT(*) FROM #tCalendar) > 0)
BEGIN
SET #StartTime = (SELECT TOP 1 StartTime FROM #tCalendar)
SET #EndTime = (SELECT TOP 1 EndTime FROM #tCalendar)
SET #StartHour = (SELECT TOP 1 DATEPART(HOUR,DATEADD(HOUR,0,StartTime)) FROM #tCalendar)
SET #EndHour = (SELECT TOP 1 DATEPART(HOUR,DATEADD(HOUR,0,EndTime)) FROM #tCalendar)
WHILE #StartHour <= #EndHour
BEGIN
INSERT INTO #tCalendarHours
SELECT RequestedFor,MeetingType,RoomName,#StartHour FROM #tCalendar WHERE StartTime = #StartTime AND EndTime = #EndTime
SET #StartHour = #StartHour + 1
END
DELETE #tCalendar WHERE StartTime = #StartTime AND EndTime = #EndTime
END
Do something like this:
Declare #ID int
SET #ID = 35
SELECT
p.SomeID
,p.ProductID
FROM ListOfProducts p
WHERE p.SomeID = #ID
-----------------------
--Or if you have to join to get it
Declare #ID int
SET #ID = 35
SELECT
c.SomeID
,p.ProductID
,p.ProductName
FROM ListOfProducts p
INNER JOIN categories c on p.ProductID = c.SomeID
WHERE p.SomeID = #ID
You can use option with WHILE loop and BREAK/CONTINUE keywords
CREATE PROC dbo.yourProcName
#SomeID int
AS
BEGIN
IF OBJECT_ID('tempdb.dbo.#resultTable') IS NOT NULL DROP TABLE dbo.#resultTable
CREATE TABLE dbo.#resultTable
(Col1 int, Col2 int)
DECLARE #ProductID int = 0
WHILE(1=1)
BEGIN
SELECT #ProductID = MIN(ProductID)
FROM ListOfProducts
WHERE SomeID = #SomeID AND ProductID > #ProductID
IF #ProductID IS NULL
BREAK
ELSE
INSERT dbo.#resultTable
SELECT Col1, Col2
FROM dbo.yourSearchTable
WHERE ProductID = #ProductID
CONTINUE
END
SELECT *
FROM dbo.#resultTable
END
Demo on SQLFiddle