SQL Return to front end - sql

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.

Related

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;

Create View dynamically from SP in sql server 2012

sql server 2012
i have created a SP to create view dynamically with Parameter i supplied.
below is the code
i am not sure why i am getting the below error.
Msg 102, Level 15, State 1, Procedure uspCreateView, Line 10
Incorrect syntax near '#VIEWNM'.
Code:
CREATE PROCEDURE uspCreateView
#VIEWNM VARCHAR(50),
#COMP INT,
#TODT DATE = 9999-12-31
AS
EXEC ('
CREATE VIEW +'#VIEWNM'
AS
(
SELECT
COL1,
COL2,
COL3,
DATE,
SKU,
CASE WHEN IsRowCurrent = 1 THEN '#TODT' ELSE dateadd(MILLISECOND, -1000 - datepart(MILLISECOND, FMDT), FMDT) END AS TODT,
FROM MYTABLE mt
OUTER APPLY ( SELECT MAX(DATEADD(second, -1, FMDT)) TO_DATE
FROM MYTABLE mt2
WHERE mt2.COL1 = mt.COL1
AND mt2.COL2 = mt.COL2
AND mt2.FMDT > mt.FMDT
AND mt.COL3 = '#COMPID' ) oa
WHERE mt.COL3 = '#COMPID'
)
please help me to fix the below error.
Thanks
I am not sure, why you want to create views dynamically, ideally views should be created before hand only, and you will be required to fetch the data depending on the condition.
Still if you want to proceed, you should do it proper way to avoid any issues. I can see there are issues with your implementation. Ideally you should make it parameterized, like following sample query to avoid any SQL injection.
There are issues with your provided code also, I tried to fix some of these.
CREATE PROCEDURE uspCreateView
(
#VIEWNM VARCHAR(50),
#COMP INT,
#TODT DATE = '9999-12-31'
)
AS
BEGIN
DECLARE #Query NVARCHAR(MAX)
DECLARE #ParmDefinition nvarchar(MAX);
SET #Query = N'CREATE VIEW #VIEWNM_I AS ( SELECT COL1, COL2, COL3, DATE, SKU,
CASE WHEN IsRowCurrent = 1 THEN #TODT_I ELSE
dateadd(MILLISECOND, -1000 - datepart(MILLISECOND, FMDT)
, FMDT) END AS TODT, FROM MYTABLE mt OUTER APPLY (
SELECT MAX(DATEADD(second, -1, FMDT)) TO_DATE
FROM MYTABLE mt2
WHERE mt2.COL1 = mt.COL1
AND mt2.COL2 = mt.COL2
AND mt2.FMDT > mt.FMDT
AND mt.COL3 = #COMPID_I ) oa
WHERE mt.COL3 = #COMPID_I)'
SET #ParmDefinition = N'#VIEWNM VARCHAR(100),#TODT_I DATETIME,#COMP_I INT';
EXECUTE sp_executesql #Query,#ParmDefinition, #VIEWNM_I=#VIEWNM, #COMP_I=#COMP, #TODT_I=#TODT
END
Try this
Command(s) completed successfully.
CREATE PROCEDURE uspCreateView
#VIEWNM VARCHAR(50),
#COMP INT,
#TODT DATE = '9999-12-31'
AS
EXEC ('
CREATE VIEW '+#VIEWNM+'
AS
(
SELECT
COL1,
COL2,
COL3,
DATE,
SKU,
CASE WHEN IsRowCurrent = 1 THEN '+#TODT+' ELSE dateadd(MILLISECOND, -1000 - datepart(MILLISECOND, FMDT), FMDT) END AS TODT,
FROM MYTABLE mt
OUTER APPLY ( SELECT MAX(DATEADD(second, -1, FMDT)) TO_DATE
FROM MYTABLE mt2
WHERE mt2.COL1 = mt.COL1
AND mt2.COL2 = mt.COL2
AND mt2.FMDT > mt.FMDT
AND mt.COL3 = '+#COMP+' ) oa
WHERE mt.COL3 = '+#COMP+'
) ')
It should be
CREATE VIEW ' + #VIEWNM + ' AS...

Parameter Sniffing Not working

I am using MSSQL. I have a stored procedure which works fine for couple of days and later on it becomes slow. I came to know that Parameter Sniffing will work for it. How ever after implementing it it became slow for ever. I also tried to Recompiling job. I faced the same slowness issue immediately.
Can some one please help me with this ?
Below is the structure of my Stored Procedure.
#START_VALUE int=null,
#END_VALUE int=null
#UID NVARCHAR(MAX)=null,
AS
BEGIN
SELECT
dbo.TABLE1.ID,
ROW_NUMBER() OVER (ORDER BY TABLE1.UPDATED_ON desc) AS RN,
CONVERT(VARCHAR(10), dbo.TABLE1.DATE, 101) AS TDATE,
CATEGORY = (
SELECT TOP 1 COLUMN1
FROM TABLE5 CT1
WHERE TABLE1.CATEGORY = CT1.CATEGORY_ID
),
TYPETEXT = (
SELECT TOP 1 COLUMN1
FROM TABLE6 CT1
WHERE TABLE1.TYPE = CT1.TYPE_ID
),
IMAGE = STUFF(( SELECT DISTINCT ',' + CAST(pm.C1 AS varchar(12))
FROM TABLE2 pm
WHERE pm.ID = TABLE1.ID AND pm.C1 IS NOT NULL AND pm.C1 <> ''
FOR XML PATH('')),
1, 1, '' ) INTO #tempRecords
FROM dbo.TABLE1
WHERE ((#UID is null OR dbo.TABLE1.ID = #UID )
ORDER BY TABLE1.UPDATED DESC
SELECT #count = COUNT(*) FROM #tempRecords;
SELECT *, CONVERT([int],#count) AS 'TOTAL_RECORDS'
FROM #tempRecords
WHERE #tempRecords.RN BETWEEN CONVERT([bigint], #START_VALUE) AND CONVERT([bigint], #END_VALUE)
END
GO
To make the query optimized for parameter sniffing, declare dummy variables and use them in your query, as opposed to using the original parameters as such.
CREATE PROCEDURE test_proc
#START_VALUE INT=NULL,
#END_VALUE INT=NULL,
#UID NVARCHAR(max)=NULL
as
BEGIN
DECLARE #START_VALUE_SNIFF INT=NULL,
#END_VALUE_SNIFF INT=NULL,
#UID_SNIFF NVARCHAR(max)=NULL
SET #START_VALUE_SNIFF = #START_VALUE
SET #END_VALUE_SNIFF = #END_VALUE
SET #UID_SNIFF = #UID
select * from
FROM dbo.TABLE1
WHERE ((#UID_SNIFF is null OR dbo.TABLE1.ID = #UID_SNIFF )
ORDER BY TABLE1.UPDATED DESC
END

T-SQL Dynamic variable insert

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)

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