Working with stored procedures in Visual Studio 2012 - entity-framework

We have a person search stored procedure in our database, which I want to map into Visual Studio 2012 in my edmx file. The stored procedure returns the rows that satisfy the search and it sets a return code. When I execute the stored procedure manually I get the 4 rows I expect and I get a return code of 0.
I am using 2012, EF 5, and Entity Framework components in the framework.
When I select the stored procedure via UpdateModelFromDatabase and add it to my project, instead of defining the usual {storedProcedureName}_Result and returning that, it is translated to return only an integer. This prevents me from using the stored procedure to actually get to the rows to display them.
Interestingly enough, we have a test PersonSearch stored procedure which happens to be broken, but it is the same stored procedure with some internal changes. It still returns the results of the search AND sets the return code. When I pull that second stored procedure in, it does as expected and creates the stored procedure as returning the {storedProcedureName}_Result and returning the rows.
Has anyone seen this issue and how do I work around this issue? I need this first stored procedure to return the rows, not the return code.
Follow Up
I came across this question and had my DBA look at it. But making similar changes to our stored procedure still has EF returning an integer instead of a complex object.
I also ran the sproc with all fields null and it returned the empty table structure in addition to the return code.
This is the stored procedure:
USE [ourdatabase]
GO
/****** Object: StoredProcedure [dbo].[usp_Person_SearchPerson] Script Date: 01/30/2013 11:46:31 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[usp_Person_SearchPerson]
#firstName nvarchar(50), --OR
#lastName nvarchar(50), --OR
#companyName nvarchar(150), --OR
#phoneNumber1 nvarchar(50), --OR
#phoneNumber2 nvarchar(50), --OR
#email nvarchar(100), --OR
#franchiseSetId uniqueidentifier, --AND
#recordSourceId uniqueidentifier --AND
AS
BEGIN
SET NOCOUNT ON;
DECLARE #ReturnTable TABLE
(
PersonID UNIQUEIDENTIFIER,
FirstName NVARCHAR(50),
LastName NVARCHAR(50),
CompanyName NVARCHAR(150),
EmailAddress NVARCHAR(100),
PhoneNumber1 NVARCHAR(50),
PhoneNumber2 NVARCHAR(50),
Address1 NVARCHAR(50),
City NVARCHAR(100),
State NVARCHAR(50),
PostalCode NVARCHAR(20),
Score INT
)
-- flags to be used instead of calling the function udf_Strings_IsNullOrEmpty repeatedly
Declare
#firstNamebit bit, --OR
#lastNamebit bit, --OR
#companyNamebit bit, --OR
#phoneNumber1bit bit, --OR
#phoneNumber2bit bit, --OR
#emailbit bit, --OR
#franchiseSetIdbit bit, --AND
#recordSourceIdbit bit,
#rowID int
Insert into AppToolData..SearchLog
(
firstname ,
lastname ,
companyName ,
phoneNumber1 ,
phoneNumber2 ,
email ,
franchiseSetId ,
recordSourceID ,
StartTime_UTC
)
Values
(
#firstname ,
#lastname ,
#companyName ,
#phoneNumber1 ,
#phoneNumber2 ,
#email ,
#franchiseSetId ,
#recordSourceID ,
SYSDATETIMEOFFSET()
)
Select #rowID = SCOPE_IDENTITY()
-- working set to accumulate Person records meeting search criteria
--Declare #People table
Create Table #People
(
PersonID uniqueIdentifier
)
--work set of distinct person reocrds from previous working set
Declare #DistinctPeople table
(
PersonID uniqueIdentifier not null Primary Key
)
--Set flags
Select -- 0 = False (Is Not Null) 1 = True (Is Null)
#firstNamebit = dbo.udf_Strings_IsNullOrEmpty(#firstName),
#lastNamebit = dbo.udf_Strings_IsNullOrEmpty(#lastName),
#companyNamebit = dbo.udf_Strings_IsNullOrEmpty(#companyName),
#phoneNumber1bit = dbo.udf_Strings_IsNullOrEmpty(#phoneNumber1),
#phoneNumber2bit = dbo.udf_Strings_IsNullOrEmpty(#phoneNumber2),
#emailbit = dbo.udf_Strings_IsNullOrEmpty(#email)
DECLARE #MinimumWeight INT
SET #MinimumWeight = 1
DECLARE #AvailableWeight INT
SET #AvailableWeight = 0
If #franchiseSetId is not null
Begin
Select #firstName = '%'+#firstName+'%'
Select #lastName = '%'+#lastName+'%'
End
Else
Begin
Select #firstName = #firstName+'%'
Select #lastName = #lastName+'%'
End
If #franchiseSetId is null
Begin
-- first name provided, last name not provided, phone number not provided
IF #firstNamebit = 0 and #lastNamebit = 1 and #phoneNumber1bit = 1
BEGIN
SET #AvailableWeight = #AvailableWeight + 15 -- (First Name = 15, Last Name = 20, Phone Number = 30)
-- Add records where first name is a partial string match
Insert into #People
Select PersonID from Person p
Where (PatIndex(#firstName, p.FirstName)>0)
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
-- first name not provided, last name provided, phone number not provided
Else IF #firstNamebit = 1 and #lastNamebit = 0 and #phoneNumber1bit = 1
BEGIN
SET #AvailableWeight = #AvailableWeight + 20 -- (First Name = 15, Last Name = 20, Phone Number = 30)
-- Add records where last name is a partial string match
Insert into #People
Select PersonID from Person p
Where
(PatIndex(#lastName, p.lastName)>0)
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
-- first name provided, last name provided, phone number not provided
Else IF #firstNamebit = 0 and #lastNamebit = 0 and #phoneNumber1bit = 1
BEGIN
SET #AvailableWeight = #AvailableWeight + 30 -- (First Name = 15, Last Name = 20, Phone Number = 30)
-- Add records where first & last name are a partial string match
Insert into #People
Select PersonID from Person p
Where
(
(PatIndex(#firstName, p.FirstName)>0)
and
(PatIndex(#lastName, p.lastName)>0)
)
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
-- first name provided, last name not provided, phone number provided
IF #firstNamebit = 0 and #lastNamebit = 1 and #phoneNumber1bit = 0
BEGIN
SET #AvailableWeight = #AvailableWeight + 45 -- (First Name = 15, Last Name = 20, Phone Number = 30)
-- Add records where first name is a partial string match
-- and Phone Number is an exact match
Insert into #People
SELECT
p.PersonId
FROM
Person p WITH (NOLOCK)
LEFT OUTER JOIN
PersonPhoneNumber ppn1 WITH (NOLOCK)
ON p.PersonId=ppn1.PersonId
LEFT OUTER JOIN
PhoneNumber pn1 WITH (NOLOCK)
ON ppn1.PhoneNumberId=pn1.PhoneNumberId
Where
(PatIndex(#firstName, p.FirstName)>0)
and
pn1.Number = #PhoneNumber1
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
-- first name not provided, last name provided, phone number provided
Else IF #firstNamebit = 1 and #lastNamebit = 0 and #phoneNumber1bit = 0
BEGIN
SET #AvailableWeight = #AvailableWeight + 50 -- (First Name = 15, Last Name = 20, Phone Number = 30)
-- Add records where last name is a partial string match
-- and Phone Number is an exact match
Insert into #People
SELECT
p.PersonId
FROM
Person p WITH (NOLOCK)
LEFT OUTER JOIN
PersonPhoneNumber ppn1 WITH (NOLOCK)
ON p.PersonId=ppn1.PersonId
LEFT OUTER JOIN
PhoneNumber pn1 WITH (NOLOCK)
ON ppn1.PhoneNumberId=pn1.PhoneNumberId
Where
(PatIndex(#lastName, p.LastName)>0)
and
pn1.Number = #PhoneNumber1
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
-- first name provided, last name provided, phone number provided
Else IF #firstNamebit = 0 and #lastNamebit = 0 and #phoneNumber1bit = 0
BEGIN
SET #AvailableWeight = #AvailableWeight + 65 -- (First Name = 15, Last Name = 20, Phone Number = 30)
-- Add records where first & last name are a partial string match
-- and Phone Number is an exact match
Insert into #People
SELECT
p.PersonId
FROM
Person p WITH (NOLOCK)
LEFT OUTER JOIN
PersonPhoneNumber ppn1 WITH (NOLOCK)
ON p.PersonId=ppn1.PersonId
LEFT OUTER JOIN
PhoneNumber pn1 WITH (NOLOCK)
ON ppn1.PhoneNumberId=pn1.PhoneNumberId
Where
(
(PatIndex(#firstName, p.FirstName)>0)
and
(PatIndex(#lastName, p.LastName)>0)
)
and
pn1.Number = #PhoneNumber1
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
-- first name not provided, last name not provided, phone number provided
Else IF #firstNamebit = 1 and #lastNamebit = 1 and #phoneNumber1bit = 0
BEGIN
SET #AvailableWeight = #AvailableWeight + 30 -- (First Name = 15, Last Name = 20, Phone Number = 30)
-- Add records where Phone Number is an exact match
Insert into #People
SELECT
p.PersonId
FROM
Person p WITH (NOLOCK)
LEFT OUTER JOIN
PersonPhoneNumber ppn1 WITH (NOLOCK)
ON p.PersonId=ppn1.PersonId
LEFT OUTER JOIN
PhoneNumber pn1 WITH (NOLOCK)
ON ppn1.PhoneNumberId=pn1.PhoneNumberId
Where
pn1.Number = #PhoneNumber1
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
End
Else -- Indicates WORKCENTER/Drybook search
Begin
IF #firstNamebit = 0
BEGIN
SET #AvailableWeight = #AvailableWeight + 15
-- Add records where first name is a partial string match
Insert into #People
Select PersonID from Person p
Where (PatIndex(#firstName, p.FirstName)>0)
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
IF #lastNamebit = 0
BEGIN
SET #AvailableWeight = #AvailableWeight + 20
-- Add records where last name is a partial string match
Insert into #People
Select PersonID from Person p
Where
(PatIndex(#lastName, p.lastName)>0)
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
IF #phoneNumber1bit = 0
BEGIN
SET #AvailableWeight = #AvailableWeight + 30
-- Add records where Phone Number 1 is an exact match
Insert into #People
SELECT
p.PersonId
FROM
Person p WITH (NOLOCK)
LEFT OUTER JOIN
PersonPhoneNumber ppn1 WITH (NOLOCK)
ON p.PersonId=ppn1.PersonId
LEFT OUTER JOIN
PhoneNumber pn1 WITH (NOLOCK)
ON ppn1.PhoneNumberId=pn1.PhoneNumberId
Where pn1.Number = #PhoneNumber1
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
End
IF #phoneNumber2bit = 0
BEGIN
SET #AvailableWeight = #AvailableWeight + 30
-- Add records where Phone Number 2 is an exact match
Insert into #People
SELECT
p.PersonId
FROM
Person p WITH (NOLOCK)
LEFT OUTER JOIN
PersonPhoneNumber ppn1 WITH (NOLOCK)
ON p.PersonId=ppn1.PersonId
LEFT OUTER JOIN
PhoneNumber pn1 WITH (NOLOCK)
ON ppn1.PhoneNumberId=pn1.PhoneNumberId
Where pn1.Number = #PhoneNumber2
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
IF #emailbit = 0
BEGIN
SET #AvailableWeight = #AvailableWeight + 40
-- Add records where Email is an exact match
Insert into #People
Select
p.PersonId
from Person p
LEFT OUTER JOIN
PersonEmailAddress pea WITH (NOLOCK)
ON p.PersonId=pea.PersonId
LEFT OUTER JOIN
EmailAddress ea WITH (NOLOCK)
ON pea.EmailAddressId=ea.EmailAddressId
Where ea.[Address] = #email
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
IF #companyNamebit = 0
BEGIN
SET #AvailableWeight = #AvailableWeight + 10
-- Add records where Company Name is an exact match
Insert into #People
Select
p.PersonId
from Person p
LEFT OUTER JOIN
Company c WITH (NOLOCK)
ON p.CompanyId=c.CompanyId
Where c.Name = #companyName
AND
(
p.RecordSourceId = Coalesce(#recordSourceId, p.RecordSourceId)
--(#recordSourceId IS NULL)
--OR
--(p.RecordSourceId = #recordSourceId)
)
AND
(
p.FranchiseSetId = Coalesce(#franchiseSetId, p.FranchiseSetId)
--(#franchiseSetId IS NULL AND p.FranchiseSetId IS NULL)
--OR
--(p.FranchiseSetId = #franchiseSetId)
)
END
If #franchiseSetId is not null
Begin
-- WORKCENTER -- do not return results that are less than a 40% match of what was passed in
SET #MinimumWeight = #AvailableWeight * 0.4
End
Else
Begin
-- ClaimsEntry -- do not return results that are less than a 60% match of what was passed in
SET #MinimumWeight = #AvailableWeight * 0.6
End
-- get list of unique records
Insert into #DistinctPeople
Select Distinct PersonID from #People order by PersonID
INSERT INTO #ReturnTable (PersonID, FirstName, LastName, CompanyName, EmailAddress, PhoneNumber1, PhoneNumber2, Score)
(
SELECT
DistinctPeople.PersonId,
p.FirstName,
p.LastName,
c.Name,
ea.[Address],
null as PhoneNumber1,
null as PhoneNumber2,
Score =
(
--first name score
(
(CASE WHEN #firstNamebit = 0 THEN 1 ELSE 0 END)
*
(CASE WHEN PatIndex(#firstName, p.FirstName)>0 THEN 1 ELSE 0 END)
*
15
)
+
--last name score
(
(CASE WHEN #lastNamebit = 0 THEN 1 ELSE 0 END)
*
(CASE WHEN PatIndex(#lastName, p.LastName)>0 THEN 1 ELSE 0 END)
*
20
)
+
--email score
(
(CASE WHEN #emailbit = 0 THEN 1 ELSE 0 END)
*
(CASE WHEN ea.[Address] = #email THEN 1 ELSE 0 END)
*
40
)
+
--company score
(
(CASE WHEN #companyNamebit = 0 THEN 1 ELSE 0 END)
*
(CASE WHEN PatIndex(#companyName, c.Name)>0 THEN 1 ELSE 0 END)
*
10
)
)
FROM
#DistinctPeople DistinctPeople
LEFT OUTER JOIN
Person p WITH (NOLOCK)
ON DistinctPeople.PersonId=p.PersonId
LEFT OUTER JOIN
PersonEmailAddress pea WITH (NOLOCK)
ON p.PersonId=pea.PersonId
LEFT OUTER JOIN
EmailAddress ea WITH (NOLOCK)
ON pea.EmailAddressId=ea.EmailAddressId
LEFT OUTER JOIN Company c WITH (NOLOCK)
ON p.CompanyId=c.CompanyId
)
--If neither Phone number was passed as a parameter, the scores will not change
-- We can get rid of records that will not be returned
If #phoneNumber1bit = 1 and #phoneNumber2bit = 1
Begin
-- update the phone number scores, the actual phone number values
-- can be in either the first or second position
UPDATE rt
SET Score = Score +
(
(CASE WHEN #phoneNumber1bit = 0 THEN 1 ELSE 0 END)
*
(CASE WHEN rt.PhoneNumber1 = #phoneNumber1 THEN 1
WHEN rt.PhoneNumber2 = #phoneNumber1 THEN 1 ELSE 0 END)
*
30
)
+
--phone 2 score
(
(CASE WHEN #phoneNumber2bit = 0 THEN 1 ELSE 0 END)
*
(CASE WHEN rt.PhoneNumber1 = #phoneNumber2 THEN 1
WHEN rt.PhoneNumber2 = #phoneNumber2 THEN 1 ELSE 0 END)
*
30
)
FROM #ReturnTable rt
-- clear out the records we no longer care about
DELETE FROM #ReturnTable WHERE Score < #MinimumWeight
End
UPDATE rt
SET rt.PhoneNumber1 =
(
select top 1 xpn1.number
from PersonPhoneNumber xppn1 WITH (NOLOCK)
LEFT OUTER JOIN
PhoneNumber xpn1 WITH (NOLOCK)
on xppn1.PhoneNumberId =xpn1.PhoneNumberId
where xppn1.PersonId = rt.PersonID
order by (CASE
WHEN xpn1.Number = #phoneNumber1 then -999
else xppn1.SequenceNumber
end )
)
FROM #ReturnTable rt
UPDATE rt
SET rt.PhoneNumber2 =
(
select top 1 xpn1.number from PersonPhoneNumber xppn1 WITH (NOLOCK)
LEFT OUTER JOIN PhoneNumber xpn1 WITH (NOLOCK) on xppn1.PhoneNumberId =xpn1.PhoneNumberId
where xppn1.PersonId = rt.PersonID
and rt.PhoneNumber1 != xpn1.Number
order by (CASE
WHEN xpn1.Number = #phoneNumber2 then -998
else xppn1.SequenceNumber end )
)
FROM #ReturnTable rt
-- update the phone number scores, the actual phone number values can be in either the first or second position
UPDATE rt
SET Score = Score +
(
(CASE WHEN #phoneNumber1bit = 0 THEN 1 ELSE 0 END)
*
(CASE WHEN rt.PhoneNumber1 = #phoneNumber1 THEN 1
WHEN rt.PhoneNumber2 = #phoneNumber1 THEN 1 ELSE 0 END)
*
30
)
+
--phone 2 score
(
(CASE WHEN #phoneNumber2bit = 0 THEN 1 ELSE 0 END)
*
(CASE WHEN rt.PhoneNumber1 = #phoneNumber2 THEN 1
WHEN rt.PhoneNumber2 = #phoneNumber2 THEN 1 ELSE 0 END)
*
30
)
FROM #ReturnTable rt
-- clear out the records we no longer care about
DELETE FROM #ReturnTable WHERE Score < #MinimumWeight
UPDATE rt
SET Address1 = a.Address1,
City = a.City,
State = s.Abbreviation,
PostalCode = a.PostalCode
FROM #ReturnTable rt
OUTER APPLY
(
SELECT TOP 1 *
FROM PersonAddress pa WITH (NOLOCK)
WHERE pa.PersonId = rt.PersonID
ORDER BY pa.SequenceNumber
) ppa
LEFT JOIN Address a WITH (NOLOCK) on ppa.AddressId = a.AddressId
LEFT JOIN State s WITH (NOLOCK) on a.StateId = s.StateId
Update AppToolData..SearchLog
Set EndTime_UTC = SYSDATETIMEOFFSET()
Where rowid = #rowid
-- return only those that meet the minimum score/weight requirements
Delete FROM #ReturnTable WHERE Score < #MinimumWeight
SELECT * FROM #ReturnTable
--order by Score Desc
END

Based on information from cadrell0 and our own tests we found the following:
A stored procedure that is generating a table and returning rows from that table are doing this only at runtime. When called by Entity Framework with fmtonly it throws an error because the runtime object is not created.
We added FMTONLY OFF to our stored procedure which allowed Entity Framework to see the format of the table and, thus, the format for the complex object.
This allowed me to add the stored procedure, get the correct returned object, and now I'm able to use the sproc to execute our search on the database side of the fence.
This was important to us as the original code is using this and our code HAD to use it.

Related

T-SQL to check and update

Getting error:
Msg 512, Level 16, State 1, Line 48
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Msg 512, Level 16, State 1, Line 87
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Need to check each record in the table and update a table if there is no records = to 0,00. Then update an existing table with current values. I want to be able to track current data and compare with old data.
DECLARE #LocTime DATETIME;
DECLARE #MinDateTime DATETIME;
DECLARE #SystemDateTime DATETIME;
DECLARE #LIR MONEY;
DECLARE #LOAR MONEY;
SELECT #SystemDateTime = SYSDATETIME(); --= '2016-12-07 23:30:00'
SELECT #MinDateTime = DATEADD(mi,-30,#SystemDateTime) --go back half hour of reads, job is running every 10 minutes for overlap
--select #MinDateTime, #SystemDateTime
IF OBJECT_ID(N'tempdb..##LastOver2') IS NOT NULL
BEGIN
DROP TABLE ##LastOver2
END
--make temp table to hold found data
CREATE TABLE ##LastOver2 (ReadDate DATETIME
, FacilityName NVARCHAR(100)
, FacilityID UNIQUEIDENTIFIER
, LastInstantRead MONEY
, LastOverAllRead MONEY
, FacilityTimeZone INT
, FacilityTime DATETIME)
INSERT INTO ##LastOver2 (ReadDate, FacilityName
, FacilityID, LastInstantRead
, LastOverAllRead
, FacilityTimeZone, FacilityTime)
SELECT DISTINCT --why distinct?
fmr.ReadDate, f.Name
, f.FacilityID, fm.LastInstantRead
, fm.LastOverAllRead
, f.Timezone
, #LocTime
FROM [dbo].[Facilities] f WITH (NOLOCK)
JOIN [dbo].[FacilityMeters] fm WITH (NOLOCK)
ON F.FacilityID = FM.FacilityID
JOIN FacilityMeterReadings fmr WITH (NOLOCK)
ON FM.FacilityMeterID = FMR.FacilityMeterID
WHERE --fm.FacilityMeterID = '9268d1af-cc29-432c-9cdb-06c158180d2f'
(fmr.ReadDate >= #MinDateTime and ReadDate <= #SystemDateTime) --including on both side to continue with overlap
and (fm.IsVirtual = 0 and fm.ParentMeterID is NULL)
--and (fm.LastInstantRead = 0.00 and fm.LastOverAllRead = 0.00)
AND f.SuppressMonitoring = 0
select * from ##LastOver2
IF (select LastInstantRead from ##LastOver2) = 0.00 OR (SELECT LastOverAllRead FROM ##LastOver2) = 0.00
BEGIN
--UPDATE dbo.Facilities
--SET SuppressMonitoring = 1
-- FROM dbo.Facilities F
-- JOIN ##LastOver L
-- ON F.FacilityID = l.FacilityID
-- WHERE F.FacilityID = l.FacilityID
DECLARE #body_content NVARCHAR(150);
DECLARE #StartHour NVARCHAR(8) = '08:30:00' ;
DECLARE #StopHour NVARCHAR(8) = '16:00:00';
--why distinct, is it already distinct. Is is supposed to distinct the facility or meter?
DECLARE #SQLScript NVARCHAR(200) = 'SELECT distinct * FROM ##LastOver2 WHERE CONVERT(TIME, FacilityTime) BETWEEN '
+ CHAR(39) + #StartHour + CHAR(39) +' AND ' + CHAR(39) + #StopHour + CHAR(39);
--only looking for reads during day hours? shouldn't use between.
DECLARE #copyRecipients NVARCHAR(100)
SET #body_content = 'Please check the attached file. This was from server: ' + ##SERVERNAME
DECLARE #fileName nvarchar(255);
select #fileName = 'BadReading_' + replace(replace(convert(nvarchar(19),getdate(), 126),':',''),'-','') + '.txt';
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'SQLSupport'
,#recipients = 'Btest#test.com'
--, #recipients = 'jira#cleanenergycollective.atlassian.net'
--, #copy_recipients= #copyRecipients
--, #copy_recipients= 'Bill.Lugaila#easycleanenergy.com;yvonne.lewis#easycleanenergy.com;don.munroe#easycleanenergy.com;Justin.Reed#easycleanenergy.com'
, #query = #SQLScript
, #subject = 'Facility Meter Check and Updating table' --change so easier to see in emails
, #body= #body_content
, #importance= 'High'
, #attach_query_result_as_file = 1
, #query_attachment_filename = #fileName ;
--select #SQLScript
END
ELSE IF (select LastInstantRead from ##LastOver2) != 0.00 OR (SELECT LastOverAllRead FROM ##LastOver2) != 0.00
BEGIN
UPDATE [dbo].[_LastInstant_OverAll_Read]
SET [FacilityName] = lo.FacilityName,
[LastInstantRead] = lo.LastInstantRead,
[LastOverAllRead]= lo.LastOverAllRead,
[Time_Date] = (SELECT CONVERT(DateTime, SysDateTime()))
FROM ##LastOver2 lo
WHERE lo.FacilityName = [dbo].[_LastInstant_OverAll_Read].FacilityName
AND lo.LastInstantRead != [dbo].[_LastInstant_OverAll_Read].LastInstantRead
AND lo.LastOverAllRead != [dbo].[_LastInstant_OverAll_Read].LastOverAllRead
END
the following could be returning multiple rows:
.
.
.
IF
(
SELECT LastInstantRead
FROM ##LastOver2
) = 0.00
OR
(
SELECT LastOverAllRead
FROM ##LastOver2
) = 0.00
.
.
.
IF
(
SELECT LastInstantRead
FROM ##LastOver2
) != 0.00
OR
(
SELECT LastOverAllRead
FROM ##LastOver2
) != 0.00
if you are expecting them to return only 1 row then you will need to fix the issue with the following query:
SELECT DISTINCT --why distinct?
fmr.ReadDate,
f.Name,
f.FacilityID,
fm.LastInstantRead,
fm.LastOverAllRead,
f.Timezone,
#LocTime
FROM [dbo].[Facilities] f WITH (NOLOCK)
JOIN [dbo].[FacilityMeters] fm WITH (NOLOCK) ON F.FacilityID = FM.FacilityID
JOIN FacilityMeterReadings fmr WITH (NOLOCK) ON FM.FacilityMeterID = FMR.FacilityMeterID
WHERE --fm.FacilityMeterID = '9268d1af-cc29-432c-9cdb-06c158180d2f'
(fmr.ReadDate >= #MinDateTime
AND ReadDate <= #SystemDateTime) --including on both side to continue with overlap
AND (fm.IsVirtual = 0
AND fm.ParentMeterID IS NULL)
--and (fm.LastInstantRead = 0.00 and fm.LastOverAllRead = 0.00)
AND f.SuppressMonitoring = 0;

My stored procedure text search is buggy

I'm stuck - I have this nice little text searcher I've put together.
I realised I needed to count lnies in individual blocks of text that the stored procedure is stored in, so I think I've figured a way to do that.
But it's not getting every instance of a search term in a stored procedure - and I think it's the same reason... the search term is split across a text boundary.
I've looked at how to change my query - and I'm coming up blank. The skills involved to change it are beyond me!
--Text searcher.
DECLARE #searchString VARCHAR(255),
#doesNotContain VARCHAR(255),
#previewLength INTEGER,
#findStoredProcedures VARCHAR(3),
#findTableFunction VARCHAR(3),
#findScalerFunction VARCHAR(3),
#findTrigger VARCHAR(3),
#findView VARCHAR(3),
#findUserTable VARCHAR(3),
#onlyInName VARCHAR(3)
--------------------------------------------------------
-- Search criteria:
SET #searchString = 'My search Term'
SET #findStoredProcedures = 'yes'
SET #findTableFunction = 'yes'
SET #findScalerFunction = 'yes'
SET #findUserTable = 'yes'
SET #findTrigger = 'yes'
SET #findView = 'yes'
SET #doesNotContain = ''
SET #previewLength = 30
--------------------------------------------------------
SELECT DISTINCT
ISNULL(
(SELECT REPLACE(CONVERT(VARCHAR(20), (CAST(SUM(LEN(SC2.text)) AS MONEY)), 1), '.00', '')
FROM syscomments SC2 WHERE SC2.id = SO.id GROUP BY SC2.id)
, '')
AS [Object length]
,
SO.name AS [Object name]
,
CASE
WHEN SO.xtype = 'P' THEN 'Stored Procedure'
WHEN SO.xtype = 'TF' THEN 'Table Function'
WHEN SO.xtype = 'FN' THEN 'Scaler Function'
WHEN SO.xtype = 'U' THEN 'User Table'
WHEN SO.xtype = 'TR' THEN 'Trigger'
WHEN SO.xtype = 'V' THEN 'View'
END
+ ISNULL((SELECT ' - ' + name FROM sysobjects WHERE id = SO.parent_obj), '')
AS [Object type]
,
ISNULL(SUBSTRING(SC.text, CHARINDEX(#searchString, SC.text) - #previewLength, #previewLength) +
SUBSTRING(SC.text, CHARINDEX(#searchString, SC.text), #previewLength + LEN(#searchString))
, '') AS [Preview of code]
,
(SELECT
COALESCE(
SUM(LEN(SC3.text) - LEN(REPLACE(SC3.text, CHAR(13), '')) + 1) + 4
+
(
SELECT
(LEN(LEFT(SC4.text, CHARINDEX(#searchString, SC4.text))) -
LEN(REPLACE(LEFT(SC4.text, CHARINDEX(#searchString, SC4.text)), CHAR(13), '')))
FROM syscomments SC4
WHERE
SC4.id = SO.id
AND SC4.colid = SC.colid
)
,
SUM(LEN(SC3.text) - LEN(REPLACE(SC3.text, CHAR(13), '')) + 1) + 4
,
(
SELECT
(LEN(LEFT(SC4.text, CHARINDEX(#searchString, SC4.text))) -
LEN(REPLACE(LEFT(SC4.text, CHARINDEX(#searchString, SC4.text)), CHAR(13), '')) + 1)
FROM syscomments SC4
WHERE
SC4.id = SO.id
AND SC4.colid = SC.colid
)
)
FROM syscomments SC3
WHERE
SC3.id = SO.id
AND SC3.colid < SC.colid
)
AS [Line number]
FROM sysobjects SO
LEFT JOIN syscomments SC
ON SO.id = SC.id
WHERE
(
(SO.type = 'P' AND #findStoredProcedures = 'yes')
OR
(SO.type = 'TF' AND #findTableFunction = 'yes')
OR
(SO.type = 'FN' AND #findScalerFunction = 'yes')
OR
(SO.type = 'TR' AND #findTrigger = 'yes')
OR
(SO.type = 'U' AND #findUserTable = 'yes')
OR
(SO.type = 'V' AND #findView = 'yes')
)
AND SO.category = 0
AND
(
(CHARINDEX(#searchString, SC.text) > 0
AND CHARINDEX(#doesNotContain, SC.text) = 0)
OR
(SO.type = 'U'
AND CHARINDEX(#searchString, SO.name) > 0
AND CHARINDEX(#doesNotContain, SO.name) = 0)
)
ORDER BY
[Object type], [Object name], [Line number]
Your where clause seems to have an issue, this bit here
(
(CHARINDEX(#searchString, SC.text) > 0
AND CHARINDEX(#doesNotContain, SC.text) = 0)
--OR
--(SO.type = 'U'
--AND CHARINDEX(#searchString, SO.name) > 0
--AND CHARINDEX(#doesNotContain, SO.name) = 0)

Can I insert a dynamic number of rows into a table using values from the table?

I want to insert a dynamic number of rows into a table, based on information in that table.
I can do it using the code below, but I'm wondering if there's a way to avoid the loop.
The commented out section was my best attempt at what I was trying to do, but it gave me an error of:
"The reference to column "iCount" is not allowed in an argument to a TOP, OFFSET, or FETCH clause. Only references to columns at an outer scope or standalone expressions and subqueries are allowed here."
DECLARE #TableX TABLE (
TDate DATE
, TType INT
, Fruit NVARCHAR(20)
, Vegetable NVARCHAR(20)
, Meat NVARCHAR(20)
, Bread NVARCHAR(20)
)
INSERT INTO #TableX VALUES
('2016-11-10',1,'Apple','Artichoke',NULL,NULL)
, ('2016-11-10',1,'Banana','Beet',NULL,NULL)
, ('2016-11-10',1,'Canteloupe','Cauliflower',NULL,NULL)
, ('2016-11-10',1,'Durian','Daikon',NULL,NULL)
, ('2016-11-10',2,NULL,NULL,'Rabbit','Rye')
, ('2016-11-10',2,NULL,NULL,'Sausage','Sourdough')
, ('2016-11-11',1,'Elderberry','Eggplant',NULL,NULL)
, ('2016-11-11',2,NULL,NULL,'Turkey','Tortilla')
, ('2016-11-11',2,NULL,NULL,'Venison','Vienna')
SELECT * FROM #TableX
DECLARE #BlankRow TABLE (
ID INT IDENTITY
, TDate DATE
, TType INT
, iCount INT
)
DECLARE #Counter1 INT = 0
, #RowCount INT
; WITH BR1
AS (
SELECT TDate, TType, COUNT(*) AS iCount
FROM #TableX
WHERE TType = 1
GROUP BY TDate, TType
)
, BR2
AS (
SELECT TDate, TType, COUNT(*) AS iCount
FROM #TableX
WHERE TType = 2
GROUP BY TDate, TType
)
INSERT INTO #BlankRow
SELECT ISNULL(BR1.TDate, BR2.TDate) AS TDate,
CASE WHEN ISNULL(BR1.iCount,0) < ISNULL(BR2.iCount,0) THEN 1 ELSE 2 END AS TType,
ABS(ISNULL(BR1.iCount,0) - ISNULL(BR2.iCount,0)) AS iCount
FROM BR1
FULL JOIN BR2
ON BR1.TDate = BR2.TDate
WHILE #Counter1 < (SELECT MAX(ID) FROM #BlankRow)
BEGIN
SET #Counter1 += 1
SET #RowCount = (SELECT iCount FROM #BlankRow WHERE ID = #Counter1)
INSERT INTO #TableX
SELECT TOP (#RowCount) tx.TDate, br.TType, NULL, NULL, NULL, NULL
FROM #TableX tx
LEFT JOIN #BlankRow br
ON tx.TDate = br.TDate
WHERE br.ID = #Counter1
END
/*INSERT INTO #TableX
SELECT TOP (tx.iCount) tx.TDate, br.TType, NULL, NULL, NULL, NULL
FROM #TableX tx
JOIN #BlankRow br
ON tx.TDate = br.TDate*/
SELECT *
FROM #TableX
ORDER BY TDate, TType,
ISNULL(Fruit,REPLICATE(CHAR(255),20)),
ISNULL(Vegetable,REPLICATE(CHAR(255),20)),
ISNULL(Meat,REPLICATE(CHAR(255),20)),
ISNULL(Bread,REPLICATE(CHAR(255),20))
The data is silly, I know, but my end goal is to have two different Tablix's in ReportBuilder that end up with the same number of rows so the headers of my groups show up at the same place on the page.
Something like this:
declare #TableX table(TDate date
,TType int
,Fruit nvarchar(20)
,Vegetable nvarchar(20)
,Meat nvarchar(20)
,Bread nvarchar(20)
);
insert into #TableX values
('2016-11-10',1,'Apple','Artichoke',NULL,NULL)
,('2016-11-10',1,'Banana','Beet',NULL,NULL)
,('2016-11-10',1,'Canteloupe','Cauliflower',NULL,NULL)
,('2016-11-10',1,'Durian','Daikon',NULL,NULL)
,('2016-11-10',2,NULL,NULL,'Rabbit','Rye')
,('2016-11-10',2,NULL,NULL,'Sausage','Sourdough')
,('2016-11-11',1,'Elderberry','Eggplant',NULL,NULL)
,('2016-11-11',2,NULL,NULL,'Turkey','Tortilla')
,('2016-11-11',2,NULL,NULL,'Venison','Vienna');
with DataRN as
(
select *
,row_number() over (partition by TDate, TType order by TDate) rn
from #TableX
)
,RowsRN as
(
select tt.TDate
,tt.TType
,td.rn
from (select distinct TDate, TType
from #TableX
) tt
full join (select distinct t1.TDate
,row_number() over (partition by t1.TDate, t1.TType order by t1.TDate) rn
from #TableX t1
) td
on(tt.TDate = td.TDate)
)
select r.TDate
,r.TType
,d.Fruit
,d.Vegetable
,d.Meat
,d.Bread
from DataRN d
full join RowsRN r
on(d.TDate = r.TDate
and d.TType = r.TType
and d.rn = r.rn
)
order by r.TDate
,r.TType
,isnull(d.Fruit,REPLICATE(CHAR(255),20))
,isnull(d.Vegetable,REPLICATE(CHAR(255),20))
,isnull(d.Meat,REPLICATE(CHAR(255),20))
,isnull(d.Bread,REPLICATE(CHAR(255),20))
In response to your comment, here is how you would use another cte to generate the full list of dates that you would need, if you havn't got a Dates reference table already (These are tremendously useful):
declare #MinDate date = (select min(TDate) from #TableX);
declare #MaxDate date = (select max(TDate) from #TableX);
with Dates as
(
select #MinDate as DateValue
union all
select dateadd(d,1,DateValue)
from Dates
where DateValue < #MaxDate
)
select DateValue
from Dates
option (maxrecursion 0);

TSQL not generating a new value per row

I'm trying to anonymize all the data in my database, so I'm renaming all the people in it. I asked a similar question earlier, and was told to use NewID to force the creation of a new value per updated row, but in this situation it doesn't seem to be working.
What am I doing wrong?
-- Create Table Customer
CREATE TABLE #FirstName
(
ID int,
FirstName nvarchar(255) NULL,
Gender nvarchar(255) NULL
)
CREATE TABLE #LastName (
ID int,
LastName nvarchar(255)
)
-- BULK INSERT to import data from Text or CSV File
BULK INSERT #FirstName
FROM 'C:\Users\jhollon\Desktop\tmp\names\firstnames.lined.txt'
WITH
(
FIRSTROW = 1,
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n'
)
BULK INSERT #LastName
FROM 'C:\Users\jhollon\Desktop\tmp\names\lastnames.lined.txt'
WITH
(
FIRSTROW = 1,
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n'
)
/*SELECT FirstName FROM #FirstName WHERE ID = (
SELECT RandomNumber FROM (
SELECT ABS(CHECKSUM(NewID())) % 1500 AS RandomNumber FROM tblTenant WHERE Sex = '1'
) AS A
);*/
UPDATE tblTenant SET TenantName = (
SELECT LastName + ', ' + FirstName FROM
(SELECT UPPER(FirstName) as FirstName FROM #FirstName WHERE ID = (SELECT ABS(CHECKSUM(NewID())) % 500 + 1501)) AS A,
(SELECT LastName FROM #LastName WHERE ID = (SELECT ABS(CHECKSUM(NewID())) % 200 + 1)) as B
) WHERE Sex = '2';
UPDATE tblTenant SET TenantName = (
SELECT LastName + ', ' + FirstName FROM
(SELECT UPPER(FirstName) as FirstName FROM #FirstName WHERE ID = (SELECT ABS(CHECKSUM(NewID())) % 500 + 1)) AS A,
(SELECT LastName FROM #LastName WHERE ID = (SELECT ABS(CHECKSUM(NewID())) % 200 + 1)) as B
) WHERE Sex = '1';
DROP TABLE #FirstName;
DROP TABLE #LastName;
Correct. The subquery is evaluated once which is as advertised ("cachable scalar subquery")
Try this which uses NEWID as a derived table
UPDATE T
SET
TenantName = L.LastName + ', ' + F.FirstName
FROM
tblTenant T
CROSS APPLY
(SELECT TOP 1 UPPER(FirstName) as FirstName FROM #FirstName
WHERE CHECKSUM(NEWID()) <> T.ID
ORDER BY NEWID()) F
CROSS APPLY
(SELECT TOP 1 LastName FROM #LastName
WHERE CHECKSUM(NEWID()) <> T.ID
ORDER BY NEWID()) L
I'm not sure I understand your question, but if you want the ID to be unique values, you can make it an identity column.
Ex:
[ID] [int] IDENTITY(1,1) NOT NULL
The code below demonstrates that without an inner to outer correlation, that the old name is not guaranteed to differ from the new name when using the CROSS APPLY answer above.
WHERE F.Id <> T.Id ORDER BY NEWID() would be better within the FirstName CROSS APPLY
USE tempdb
GO
IF OBJECT_ID('tblTenant') IS NOT NULL
DROP TABLE tblTenant
GO
CREATE TABLE tblTenant
(
Id int,
FirstName nvarchar(20),
LastName nvarchar(20),
Gender bit
)
INSERT INTO tblTenant
VALUES (1, 'Bob' , 'Marley', 1),
(2, 'Boz' , 'Skaggs', 1)
SELECT DISTINCT FirstName
INTO #FirstNames
FROM tblTenant
SELECT DISTINCT LastName
INTO #LastNames
FROM tblTenant
-- There is a probability > 0 that a tenant's new name = tenants old name
SELECT
OldFirst = T.FirstName,
OldLast = T.LastName,
NewFirst = F.FirstName,
NewLast = L.LastName
FROM
tblTenant T
CROSS APPLY
(
SELECT TOP 1 UPPER(FirstName) AS FirstName
FROM #FirstNames
WHERE CHECKSUM(NEWID()) <> T.ID
ORDER BY NEWID()
) F
CROSS APPLY
(
SELECT TOP 1 LastName
FROM #LastNames
WHERE CHECKSUM(NEWID()) <> T.ID
ORDER BY NEWID()
) L

How to get total rows return by Stored Procedure using Userdefined Function in SQL SERVER 2005

My function
ALTER FUNCTION GetProductCount
(#CatID int)
RETURNS int
AS
BEGIN
DECLARE #return_value int
EXEC #return_value = [dbo].[USP_Products_GetList]
#ProductName = NULL,
#ProductID = NULL,
#Description = NULL,
#CatID = #CatID,
#CatName = NULL,
#Price1 = NULL,
#Price2 = NULL,
#SizeID = NULL,
#IsNew = NULL,
#InActive = NULL,
#SortBy = NULL,
#SortType = NULL
return #return_value
end
Function Execution
GetProductCount 1
Msg 557, Level 16, State 2, Procedure
GetProductCount, Line 9 Only functions
and some extended stored procedures
can be executed from within a
function.
Question
I want to find total no. of rows
result by that stored procedure and return by this function.
What should i do now?
Solution please.........
you can't do it from a UDF unless you use a loopback linked server query hack, which is not recommended
My Stored Procedure which return rows according to category id = 1
USE [StoreDB]
GO
/****** Object: StoredProcedure [dbo].[USP_Products_GetList] Script Date: 08/21/2010 03:01:32 ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER PROCEDURE [dbo].[USP_Products_GetList]
#ProductName varchar(50),
#ProductID varchar(50),
#Description varchar(50),
#CatID varchar(50),
#CatName varchar(50),
#Price1 int,
#Price2 int,
#SizeID int,
#IsNew bit,
#InActive bit,
#SortBy varchar(50),
#SortType varchar(50)
AS
SELECT ProductID, ProductName, Price Price, PriceID, [Description], Size, SizeID, IsNew, InActive, ISNULL(ImageName,'Nophoto.png') AS ImageName, ImageTitle
FROM (
SELECT DISTINCT Products.ProductID, ProductName, MAX(Price) Price, PriceID, [Description], Size, Sizes.SizeID, IsNew, InActive, ImageName, ImageTitle FROM (SELECT * FROM Products WHERE (#InActive is null or #InActive = InActive ) AND ( #IsNew is null or #IsNew = IsNew )) Products
INNER JOIN ProductCategory
on Products.ProductID = ProductCategory.ProductID
LEFT OUTER JOIN (SELECT * FROM ProductImages
WHERE ( #ProductID is null or ProductID like '%' + #ProductID + '%' ) AND Isthumb = 'true'
) ProductImages
ON Products.ProductID = ProductImages.ProductID
INNER JOIN (
SELECT CatID FROM Categories
WHERE
( (#CatID is null or #CatID = 0) or #CatID = CatID ) and
( #CatName is null or CatName like '%' + #CatName + '%' )
) Categories
on ProductCategory.CatID = Categories.CatID
INNER JOIN (
SELECT Prices.ProductID, Prices.Price, Prices.PriceID, Prices.SizeID FROM Prices
INNER JOIN (
SELECT ProductID, MAX(Price) Price from Prices WHERE PriceID IN
( SELECT MAX(PriceID) FROM Prices
GROUP BY ProductID , SizeID)
GROUP BY ProductID ) Prices_
ON Prices.ProductID = Prices_.ProductID AND Prices.Price = Prices_.Price
) as Prices
on Prices.ProductID = Products.ProductID
inner join Sizes
on Sizes.SizeID = Prices.SizeID
GROUP BY ProductName, Products.ProductID, Price, PriceID, [Description] ,Size, Sizes.SizeID, IsNew, InActive, ImageName, ImageTitle
) AS OrderProduct WHERE
( #ProductName is null or ProductName like '%' + #ProductName + '%' ) and
( #ProductID is null or ProductID like '%' + #ProductID + '%' ) and
( #Description is null or [Description] like '%' + #Description + '%' ) and
( (#SizeID is null or #SizeID = 0)or SizeID = #SizeID ) and
( #Price1 is null or Price between #Price1 AND #Price2)
ORDER BY
CASE #SortType
WHEN 'desc' THEN
CASE #SortBy
WHEN 'ProductName' THEN ProductName
END
END
DESC,
CASE #SortType
WHEN 'desc' THEN
CASE #SortBy
WHEN 'ProductID' THEN ProductID
WHEN 'Price' THEN Price
END
END
DESC,
CASE #SortType
WHEN 'asc' THEN
CASE #SortBy
WHEN 'ProductName' THEN ProductName
END
END
ASC,
CASE #SortType
WHEN 'asc' THEN
CASE #SortBy
WHEN 'ProductID' THEN ProductID
WHEN 'Price' THEN Price
END
END
ASC