T-SQL Dynamic variable insert - sql

can some one help, with this query. I have 10 rows in my temp table
Declare #date date = '2014-11-01'
Declare #iDate int = '20141101'
Create table #test33(Paname varchar(100))
insert into #test33
Go
Now i have 10 rows in temp table. I want to insert those temp values in my cte dynamically
Declare #StartDate date = '2014-11-01'
Declare #EndDate date = '2014-11-30'
Declare #Paname nvarchar(100) = 'MPU' --- i have multiple panames how can i insert dyamically in cte or any other solution?
;with pla as
( SELECT*
FROM [dbo].[Pla] pl
JOIN dbo.testplan cl
ON pl.ClientId = cl.ClientId
where pl.name = #Paname
and pl.StartDate >= #StartDate and pl.EndDate <= #EndDate
)
select * from pla

You can loop throw multiple parameters using WHILE or using CURSOR. Inside it you can used dynamic sql:
declare #DSQL varchar(MAX)
SET #DSQL = ';with pla as
( SELECT*
FROM [dbo].[Pla] pl
JOIN dbo.testplan cl
ON pl.ClientId = cl.ClientId
where pl.name = '+#Paname+'
and pl.StartDate >= '+#StartDate+' and pl.EndDate <= '+#EndDate+'
)
select * from pla'
EXEC(#DSQL)

Related

Iterate through derived value from temp table so it value can be used it a where condition using for loop

I can get the total for each of the items from a derived table like so:
declare #laneNum int
declare #startDate date = '2019-02-07'
declare #class int = 1
declare #id int
if OBJECT_ID('tempdb..#tempLaneNumber') IS NOT NULL
drop table [#tempLaneNumber]
create table #tempLaneNumber
(
LANE_NUMBER INT NULL
)
INSERT INTO #tempLaneNumber (LANE_NUMBER)
SELECT DISTINCT EXIT_LANE
FROM [dbo].[TOLL]
ORDER BY EXIT_LANE DESC
select l.LANE_NUMBER, COUNT(*)
from [dbo].[TOLL] t
inner join #tempLaneNumber l on t.EXIT_LANE = l.LANE_NUMBER
where convert(date, TRXN_DTIME) = #startDate
GROUP BY l.LANE_NUMBER
But what I need now is to iterate through each of the derived values so I can use it in a statement where each result can be placed in a variable. This is what I get in my current code...
I need to put LANE_NUMBER 4 into x4 variable and LANE_NUMBER 6 into x6 variable and so forth. How do I get to it?
EDIT
declare #laneNum int
declare #startDate date = '2019-02-07'
declare #class int = 1
declare #id int
if OBJECT_ID('tempdb..#tempLaneNumber') IS NOT NULL
drop table [#tempLaneNumber]
create table #tempLaneNumber
(
LANE_NUMBER INT NULL
)
INSERT INTO #tempLaneNumber (LANE_NUMBER)
SELECT DISTINCT EXIT_LANE
FROM [dbo].[TOLL]
ORDER BY EXIT_LANE DESC
;WITH CTE AS
(
select l.LANE_NUMBER, COUNT(*) CT
from [dbo].[TOLL] t
inner join #tempLaneNumber l on t.EXIT_LANE = l.LANE_NUMBER
where convert(date, TRXN_DTIME) = #startDate
GROUP BY l.LANE_NUMBER
)
SELECT * FROM CTE where LANE_NUMBER = 4
This is about right but the problem is I would need to hardcode the value "4" or "6" or "7". This sample has 4 results so it's okay. but what if I have 10 or more?
If you want to use the result later on you can use temp table like following.
create table #Results
(
LANE_NUMBER INT NULL,
[Count_LN] INT
)
INSERT INTO #Results
select l.LANE_NUMBER, COUNT(*) CT
from [dbo].[TOLL] t
inner join #tempLaneNumber l on t.EXIT_LANE = l.LANE_NUMBER
where convert(date, TRXN_DTIME) = #startDate
GROUP BY l.LANE_NUMBER
If you want to use the output immediately in the next statement, you can go for CTE like following.
;WITH CTE AS
(
select l.LANE_NUMBER, COUNT(*) CT
from [dbo].[TOLL] t
inner join #tempLaneNumber l on t.EXIT_LANE = l.LANE_NUMBER
where convert(date, TRXN_DTIME) = #startDate
GROUP BY l.LANE_NUMBER
)
SELECT * FROM CTE --USER YOUR CTE HERE
EDIT:
I am not able to understand your requirement fully, by any reason if you want to iterate the table and store every row's column value into a variable, you can try like following.
create table #Results
(
LANE_NUMBER INT NULL,
[Count_LN] INT
)
INSERT INTO #Results
select l.LANE_NUMBER, COUNT(*) CT
from [dbo].[TOLL] t
inner join #tempLaneNumber l on t.EXIT_LANE = l.LANE_NUMBER
where convert(date, TRXN_DTIME) = #startDate
GROUP BY l.LANE_NUMBER
declare #ln int
declare #ct int
While (Select Count(*) From #Results) > 0
Begin
select top 1 #ln = LANE_NUMBER, #ct = [Count_LN] from #Results
-- Use the variable #ln and #ct. For example, if you want to call a sp
-- exec call_someothersp #ln,#ct
Delete From #Results Where LANE_NUMBER = #ln and [Count_LN]=#ct
End

How to calculate no. of days between two datetime column in SQL Server

There are two tables, T1 includes start date column and T2 includes end date column. Both the columns have both date and time.
T1 has all the rows unique while T2 can have multiple rows for same id and in all the row the end date column might be different (each row with different date and time).
I want to calculate the difference (no. of days) between End date and the start date while keeping in mind that we have to only pick the last date which is lying in the End date column.
;WITH MaxEndDate AS
(
SELECT
T2.PrimaryKey,
MaxEndDate = MAX(EndDate)
FROM
T2
GROUP BY
T2.PrimaryKey
)
SELECT
T1.PrimaryKey,
T1.StartDate,
M.MaxEndDate,
AmountDays = DATEDIFF(DAY, T1.StartDate, M.MaxEndDate)
FROM
T1
INNER JOIN MaxEndDate AS M ON T1.PrimaryKey = M.PrimaryKey
I would recommend creating a temporary table using T2 something like
Select Distinct ID
,MAX(ENDDATE) As [ENDDATE]
INTO #TMPTABLE1
then you include this into T1
Select A.ID
,Startdate
,B.ENDDATE
,Datediff(day,A.STARTDATE,B.ENDDATE) as DAYS
From T1 as A inner join
#TEMPTABLE1 as B on A.ID = B.ID
--------get no of days among multiple dates----------
DECLARE #i INT , #numrows INT , #days INT , #Fdate DATETIME , #Tdate DATETIME;
SET
#days = 0;
DECLARE #employee_table TABLE ( idx SMALLINT PRIMARY KEY IDENTITY(1,
1) ,
EmpId INT ,
SinceDate DATETIME ,
TillDate DATETIME );
-- populate employee table INSERT #employee_table
SELECT
EmpId ,
SinceDate ,
TillDate
FROM
T_EmpPosting_PIS
WHERE
EmpId = 18
AND OfficeTypeID = 1
ORDER BY
TransDate;
--SELECT
*
FROM
#employee_table -- enumerate the table
SET
#i = 1;
SET
#numrows = ( SELECT
COUNT(*)
FROM
#employee_table );
IF #numrows > 0 WHILE ( #i <= ( SELECT
MAX(idx)
FROM
#employee_table ) ) BEGIN
SET
#Fdate = ( SELECT
SinceDate
FROM
#employee_table
WHERE
idx = #i );
IF ( #i = #numrows ) BEGIN
SET
#Tdate = GETDATE();
END;
ELSE BEGIN
SET
#Tdate = ( SELECT
TillDate
FROM
#employee_table
WHERE
idx = #i );
END;
SET
#days = ( SELECT
DATEDIFF(DAY,
#Fdate,
#Tdate) ) #days;
SET
#i = #i 1;
END;
SELECT
#days;

SQL Return to front end

I have the following SQL Server stored procedure and when this is called by the front end code it returns the return value which is 0 instead of select of total count. can any one tell me what changes do i need to do to make it return the select values instead of return value
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[getTotalSent1]
(
#vendorworksationID uniqueidentifier ,
#sdate date,
#edate date
)
as
begin
select
camp.totalSent + bcamp.totalSent as totalSent
from
(select
COUNT(*) as totalSent
from
AdvertisedCampaignHistory a
where
CAST(a.CreationDate AS DATE) BETWEEN CAST(#sdate as DATE) AND CAST(#edate as DATE)
and a.CampaignID in (select cc.CampaignID
from campaign cc, VendorWorkStation vw
where cc.VendorWorkStationID = vw.VendorWorkStationID
and VendorID = #vendorworksationID)) as camp
join
(select
COUNT(*) as totalSent
from
AdvertisedCampaignHistory a
where
CAST(a.CreationDate AS DATE) BETWEEN CAST(#sdate as DATE) AND CAST(#edate as DATE)
and a.CampaignID in (select bc.BCampaignID
from BeaconCampaign bc, VendorWorkStation vw
where bc.VendorWorkStationID = vw.VendorWorkStationID
and VendorID = #vendorworksationID)) as bcamp on 1=1
end
Output:
Totalsent
---------
240
return
-----
0
It's returning 0, I want total sent value
CREATE PROCEDURE getTotalSent1
AS
DECLARE #TotalSent int
-- Do some work here
SELECT #TotalSent = 240
RETURN #TotalSent
GO
-- EXEC CODE
DECLARE #totalsent int
EXEC #totalsent = dbo.getTotalSent1
SELECT #totalsent as totalSent
ALTER procedure [dbo].[getTotalSent1]
(
#vendorworksationID uniqueidentifier ,
#sdate date,
#edate date
#total_set int output
)
as
`enter code here`
return
get param like this
declare #got_it int
exec [dbo].[getTotalSent1] xxx,yyy,#total_set=#got_it output
`
Try this:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[getTotalSent1]
(
#vendorworksationID uniqueidentifier ,
#sdate date,
#edate date
)
as
begin
DECLARE #totalSent INT
select
#totalSent =camp.totalSent + bcamp.totalSent
from
(select
COUNT(*) as totalSent
from
AdvertisedCampaignHistory a
where
CAST(a.CreationDate AS DATE) BETWEEN CAST(#sdate as DATE) AND CAST(#edate as DATE)
and a.CampaignID in (select cc.CampaignID
from campaign cc, VendorWorkStation vw
where cc.VendorWorkStationID = vw.VendorWorkStationID
and VendorID = #vendorworksationID)) as camp
join
(select
COUNT(*) as totalSent
from
AdvertisedCampaignHistory a
where
CAST(a.CreationDate AS DATE) BETWEEN CAST(#sdate as DATE) AND CAST(#edate as DATE)
and a.CampaignID in (select bc.BCampaignID
from BeaconCampaign bc, VendorWorkStation vw
where bc.VendorWorkStationID = vw.VendorWorkStationID
and VendorID = #vendorworksationID)) as bcamp on 1=1
return #totalSent
end
After BEGIN type SET NOCOUNT ON;
This disables the default return value for stored procedures, so that you get the results of your query instead.
And as a side note, you need to replace your proprietary joins with the ANSI equivalent...
e.g.
...
FROM tblA a
JOIN tblB b
ON a.key = b.key
It's better to avoid doing the join in the WHERE clause.

Left Outer Join With Date Range Only Not Working As Expected

I originally posted this question here but sadly now I have to dump the mortgage number filter. Which it turns out is a pain.
I'm using the following LOJ query which uses a CTE to generate a range of dates:
Declare #inquiryStartDate DateTime;
Declare #inquiryEndDate DateTime;
SET #inquiryStartDate = '2013-07-01';
SET #inquiryEndDate = '2013-07-31';
With DateRange As (
SELECT ID, Date
FROM d_Dates
WHERE (Date BETWEEN #inquiryStartDate AND #inquiryEndDate)
)
Select DateRange.ID, DateRange.Date,f_MortgageSnapshots.MortgageNumber, f_MortgageSnapshots.Investor_ID
From DateRange
LEFT OUTER JOIN f_MortgageSnapshots On DateRange.ID = f_MortgageSnapshots.SnapshotDate_ID
And I'm getting something like this:
But I want this:
What am I doing wrong? Can't I do a left join between tables in the case?
Quick note, There are just 2 rows in the f_MortgageSnapshots table for mortgage 12345678.
For those who are wondering, here's the d_Dates table:
It looks like d_dates does not contain a row for every possible date within your inquiry date range.
try something like:-
create function [dbo].BuildDataRange
(
#StartDate date,
#EndDate date
)
returns #returntable table
(
ID int,
[Date] date
)
as
begin
while #StartDate<=#EndDate begin
insert into #returntable (ID, [Date]) values (
DATEPART(year,#StartDate)*10000 +
DATEPART(month,#StartDate)*100 +
DATEPART(day,#StartDate),
#StartDate)
set #StartDate=DATEADD(day,1,#StartDate)
end
return
end
go
and then you should be able to:-
Declare #inquiryStartDate DateTime;
Declare #inquiryEndDate DateTime;
SET #inquiryStartDate = '2013-07-01';
SET #inquiryEndDate = '2013-07-31';
select *
from [dbo].BuildDataRange(#inquiryStartDate, #inquiryEndDate) dr
left join f_MortgageSnapshots On dr.ID = f_MortgageSnapshots.SnapshotDate_ID

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