Select unique rows from a select query result - sql

I have procedure in which I am getting data from 4 tables by joining them.
Here is my code
alter PROCEDURE [dbo].[GetServiceRequestforLead]
#professionalArea nvarchar (35) = '',
#status nvarchar (15) = '',
#experience nvarchar (15) = '',
#PageNumber BIGINT = 1,
#PageSize BIGINT =20,
#userid bigint = 0
AS
BEGIN
SELECT *
FROM (
SELECT Row_number() OVER (ORDER BY sc.Addeddate DESC) AS Row, sc.*
, TotalRows = Count(*) OVER()
FROM (
select Mod_UserDetails.Email as LeadEmailId, Mod_UserDetails.ID as LeaduserId
, ProfessionType, Mod_UserDetails.FirstName as LeadFirstName, Mod_UserDetails.LastName as LeadLastName
, Mod_UserDetails.PhoneNo1 as LeadMobile
, f.*
from Lead_RequestForm f
inner join Lead_ProfessionalArea on Lead_ProfessionalArea.ID = f.Profession
left join ServiceProviderRequestMapping on f.RequestId = ServiceProviderRequestMapping.RequestId
left join mod_userdetails on mod_userdetails.ID = ServiceProviderRequestMapping.Leaduserid
where f.ExperienceRequired like '%'+#experience+'%'
AND f.Status like '%' + #status + '%'
AND Lead_ProfessionalArea.ProfessionType like '%'+ #professionalArea +'%'
AND (ServiceProviderRequestMapping.IsDeleted is null OR ServiceProviderRequestMapping.IsDeleted = 0)
) sc
) AS query
WHERE row > ( #PageSize *( #PageNumber -1))
AND row <= ( #PageSize * #PageNumber )
END
By executing this I am getting more than one row for RequestId column of Lead_RequestForm f table. Data is unique in both the rows but reuqest id is the same. I want to get only the first record with the same Requestid column.
i have added snap here request id column has duplicate value i want only one roq with a request id so want to select first one only

You can do as below -
alter PROCEDURE [dbo].[GetServiceRequestforLead]
#professionalArea nvarchar (35) = '',
#status nvarchar (15) = '',
#experience nvarchar (15) = '',
#PageNumber BIGINT = 1,
#PageSize BIGINT =20,
#userid bigint = 0
AS
BEGIN
Select Tb.*
from
(SELECT t.*, row_number() OVER (partition by RequestId order by Rowid) as seq_nbr
FROM (
SELECT Row_number() OVER (ORDER BY sc.Addeddate DESC) AS Row, sc.*
, TotalRows = Count(*) OVER()
FROM (
select Mod_UserDetails.Email as LeadEmailId, Mod_UserDetails.ID as LeaduserId
, ProfessionType, Mod_UserDetails.FirstName as LeadFirstName, Mod_UserDetails.LastName as LeadLastName
, Mod_UserDetails.PhoneNo1 as LeadMobile
, f.*
from Lead_RequestForm f
inner join Lead_ProfessionalArea on Lead_ProfessionalArea.ID = f.Profession
left join ServiceProviderRequestMapping on f.RequestId = ServiceProviderRequestMapping.RequestId
left join mod_userdetails on mod_userdetails.ID = ServiceProviderRequestMapping.Leaduserid
where f.ExperienceRequired like '%'+#experience+'%'
AND f.Status like '%' + #status + '%'
AND Lead_ProfessionalArea.ProfessionType like '%'+ #professionalArea +'%'
AND (ServiceProviderRequestMapping.IsDeleted is null OR ServiceProviderRequestMapping.IsDeleted = 0)
) sc
) AS query
WHERE row > ( #PageSize *( #PageNumber -1))
AND row <= ( #PageSize * #PageNumber )
)t
)Tb
where Tb.seq_nbr = 1
END

Related

Pagination over join table rows

I have a SQL server request with several tables, for example:
Workorder
WorkorderOccurrence
Schedule
A workorder occurrence is a realisation of a specific schedled workorder
For workorder 1 scheduled every day I have:
Workorder occurrence 1_1 the first day
Workorder occurrence 1_2 the second day
For a workorder 2 scheduled every week I have:
Workorder occurrence 1_7
Workorder occurrence 2_1
Workorder occurence 1_8
And so ...
I have a pagination on the front for an agenda view, but the pagination must be done on workorder and not on the occurrence.
Consequently I would like to return the workorder occurrences (maybe 50, 100, 200,).
but on the 20 workorder request by the pagination. But it seems to eeturn the 20 workorder occurrence with the offset and I don't know how to do this.
Below my attempt:
CREATE FUNCTION [dbo].[FctGetWorkorderAgenda]
(
#SeverityIDsFilter NVARCHAR(MAX) = '',
#Culture NVARCHAR(MAX) = 'FR-fr',
#StartDate DATETIMEOFFSET(7),
#EndDate DATETIMEOFFSET(7),
#PageNumber INT = 0,
#ResultByPage INT = 50
)
RETURNS #resTable TABLE
(
[WorkorderID] INT NOT NULL,
[EndDate] DATETIMEOFFSET(0),
[Name] NVARCHAR(MAX),
[FixedNextDate] DATETIMEOFFSET(0),
[NextDate] DATETIMEOFFSET(0),
[WorkorderStatutType] SMALLINT NOT NULL,
[FrequenceType] SMALLINT NOT NULL,
[DayOfWeek] INT,
[DayOfMonth] INT,
[MonthType] INT,
[DayOfMonthType] INT,
[FrequencyTime] TIME(7) NOT NULL,
[FrequencyOffset] INT,
[VendorName] NVARCHAR(MAX) NOT NULL,
[EquipmentName] NVARCHAR(MAX) NOT NULL,
[OrganizationID] INT NOT NULL,
[WorkorderSeverity] INT NOT NULL,
[FullCount] INT NOT NULL
)
AS
BEGIN
INSERT INTO #resTableBooking (
WO.WorkorderID,
WO.EndDate,
WO.Name,
WOO.FixedNextDate,
WOO.NextDate,
WOO.WorkorderStatutType,
S.FrequenceType,
S.DayOfWeek,
S.DayOfMonth,
S.MonthType,
S.DayOfMonthType,
[FrequencyTime],
S.FrequencyOffset,
[EquipmentName],
[WorkorderSeverity],
[FullCount])
SELECT
WorkorderID,
EndDate,
Name,
FixedNextDate,
NextDate,
WorkorderStatutType,
FrequenceType,
DayOfWeek,
DayOfMonth,
MonthType,
DayOfMonthType,
FrequencyTime,
FrequencyOffset,
EquipmentName,
WorkorderSeverity,
FullCount
FROM (
SELECT
WO.WorkorderID,
WO.EndDate,
WO.Name,
WOO.FixedNextDate,
WOO.NextDate,
WOO.WorkorderStatutType,
S.FrequenceType,
S.DayOfWeek,
S.DayOfMonth,
S.MonthType,
S.DayOfMonthType,
S.Time AS FrequencyTime,
S.FrequencyOffset,
E.Name AS EquipmentName,
(
CASE
WHEN (WO.EndDate IS NOT NULL AND (WO.EndDate <= WO.CreatedDate OR WO.NextDate >= WO.EndDate))
THEN -5 -- WorkorderSeverity.Closed
WHEN (WO.NextDate <= WO.CreatedDate)
THEN -4 -- WorkorderSeverity.DeadlineLate
WHEN (S.FrequenceType = 3) -- FrequencyType.EveryMonth
THEN IIF(
DATEADD(day, -7, WO.NextDate) <= WO.CreatedDate,
-3 /* WorkorderSeverity.DeadlineWarning */,
-2 /* WorkorderSeverity.InTime */
)
WHEN (S.FrequenceType = 1 OR S.FrequenceType = 6)
THEN IIF(
DATEADD(month, -1, WO.NextDate) <= WO.CreatedDate,
-3 /* WorkorderSeverity.DeadlineWarning */,
-2 /* WorkorderSeverity.InTime */
)
WHEN (S.FrequenceType = 0) -- FrequencyType.None
THEN CASE
WHEN (WO.NextDate <= WO.CreatedDate) THEN -4 /* WorkorderSeverity.DeadlineLate */
WHEN (DATEADD(day, -3, WO.NextDate) <= WO.CreatedDate) THEN -3
ELSE -2
END
ELSE -2
END
) AS WorkorderSeverity,
COUNT(WO.WorkorderID) OVER() FullCount
FROM [dbo].[WorkorderOccurrence] WOO WITH(NOLOCK)
JOIN [dbo].[Workorder] WO WITH(NOLOCK) ON WO.WorkorderID = WOO.WorkorderID
JOIN [dbo].[Schedule] S WITH(NOLOCK) ON S.ScheduleID = WO.WorkorderScheduleID
JOIN [dbo].[Equipment] E WITH(NOLOCK) ON E.EquipmentID = WO.EquipmentID
LEFT JOIN dbo.Localization l WITH(NOLOCK) ON l.CultureKey = E.CultureKey AND l.CultureName = #culture
WHERE (WOO.FixedNextDate IS NOT NULL AND WOO.FixedNextDate BETWEEN #StartDate AND #EndDate
OR WOO.NextDate IS NOT NULL AND WOO.NextDate BETWEEN #StartDate AND #EndDate)
GROUP BY WO.WorkorderID, WO.EndDate, WO.Name, WO.CreatedDate, WO.NextDate,
WOO.NextDate, WOO.FixedNextDate, WOO.WorkorderOccurrenceID, WOO.WorkorderStatutType,
S.FrequenceType, S.DayOfWeek, S.DayOfMonth, S.MonthType, S.DayOfMonthType, S.Time, S.FrequencyOffset,
E.Name
) AS base
LEFT JOIN
(
SELECT [value]
FROM STRING_SPLIT(#SeverityIDsFilter, ';')
) AS DynamicSeverityFilter ON WorkorderSeverity = DynamicSeverityFilter.[value]
WHERE ((DynamicSeverityFilter.[value] IS NULL AND #SeverityIDsFilter = '') OR DynamicSeverityFilter.[value] IS NOT NULL)
ORDER BY base.WorkorderID, base.NextDate
OFFSET (#PageNumber * #ResultByPage) ROWS
FETCH NEXT #ResultByPage ROWS ONLY
RETURN
END
I think the "easiest" is to make this a two-step solution.
Fetch head data first into a table variable and use the offset thingy.
Join the head data with the row data and select "out" it together.
Simplified version of your function (but i also think you should convert it to regular procedure)
CREATE FUNCTION [dbo].[FctGetWorkorderAgenda]
(
#SeverityIDsFilter NVARCHAR(MAX) = '',
#Culture NVARCHAR(MAX) = 'FR-fr',
#StartDate DATETIMEOFFSET(7),
#EndDate DATETIMEOFFSET(7),
#PageNumber INT = 0,
#ResultByPage INT = 50
)
RETURNS #resTable TABLE
(
[WorkorderID] INT NOT NULL,
...
)
AS
BEGIN
-- Get data by filter
declare #head TABLE (workorderID INT)
insert into #head (workOrderID)
select wo.workorderID
from Workorder wo
... needed joins
where <your filters>
ORDER BY ...
OFFSET (#PageNumber * #ResultByPage) ROWS
FETCH NEXT #ResultByPage ROWS ONLY
-- Return joined data to the client
insert into #resTableBooking (
WO.WorkorderID,
...
)
SELECT WorkorderID
, ...
FROM #head h
inner join rest...
...
ORDER BY ...
RETURN
END

Refresh issue with Stored Procedure in MSSQL

I have one SP for mobile application chat app (used with API) it has 25 filters and 10 tables join and return posts for user, it works good for 2 days but after 2 days it stop working, then i need to refresh it again with alter query or something then it start working for next few days.
If filter stop for any particular user than why others have issue with SP.
USE [DatabaseName]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROC [dbo].[uspGetShoutouts] (
#UserId UNIQUEIDENTIFIER,
#anotherUserid UNIQUEIDENTIFIER,
#Interest NVARCHAR(100),
#Gender NVARCHAR(100),
#AgeFrom INT,
#AgeTo INT,
#StartLatitude NUMERIC(20,15),
#StartLongitude NUMERIC(20,15),
#Radius FLOAT,
#Location BIT = NULL,
#IsTraveler BIT,
#IsLocal BIT,
#HomeTownCity VARCHAR(100),
#UserName NVARCHAR(200),
#FirstName NVARCHAR(200),
#LastName NVARCHAR(200),
#CreatedDate DATETIME,
#IsMyShoutout BIT,
#ShoutoutTypeId INT=0,
#PostTypeId INT=0,
#oldMoment BIT,
#SortExpression CHAR(1) = 1,
#CurrentPage INT = 1,
#PageSize INT = 10,
#IsFriend BIT=0,
#IsPrivate BIT,
#GroupId NVARCHAR(200),
#TotalRows INT OUTPUT
)
AS
BEGIN
DECLARE #UserList TABLE(
UserId uniqueidentifier,
FirstName NVARCHAR(100),
LastName NVARCHAR(100),
QuickBloxId NVARCHAR(100),
SocialId NVARCHAR(100),
Gender char(1),
Email NVARCHAR(100),
IsProfileImageSync bit,
IsFriend bit,
IsRequestSent bit,
RequestSender NVARCHAR(100),
IsBlocked bit,
FriendBlocked bit,
Age int,
HomeTownCity NVARCHAR(100),
ImageName NVARCHAR(200),
Distance numeric(20,6),
DistanceTemp numeric(20,6),
LastActiveDateTime datetime,
ShoutoutGuid uniqueidentifier,
ShoutoutId bigint not null,
InterestId int,
InterestName NVARCHAR(100),
ShoutoutImageName NVARCHAR(200),
Description NVARCHAR(max),
CreatedOn DateTime,
IsImageSync bit,
DisplayUpdatedOn NVARCHAR(50),
ShoutoutCity NVARCHAR(500),
ShoutoutCountry NVARCHAR(500),
AdministrativeAreaLevel1 NVARCHAR(500),
PlaceId NVARCHAR(500),
FormattedAaddress NVARCHAR(500),
Url NVARCHAR(500),
TotalLike int,
TotalComment int,
Selflike bit,
ShoutoutTypeId int,
ShoutoutType NVARCHAR(200),
PostTypeId int,
PostTypeName NVARCHAR(200),
oldMoment bit,
UserLatitude numeric(20,6),
UserLongitude numeric(20,6),
ShoutoutLatitude numeric(20,6),
ShoutoutLongitude numeric(20,6),
DistanceShoutoutMiles numeric(20,6)
)
SET NOCOUNT ON;
DECLARE #StartLatitude1 numeric(20,2) = #StartLatitude
DECLARE #StartLongitude1 numeric(20,2) =#StartLongitude;
;with
UserList as (
select
distinct
USRSHTOUT.ShoutoutId,
USRSHTOUT.ShoutoutGuid,
U.UserId,
U.FirstName,
U.LastName,
U.QuickbloxId,
convert(int,round(datediff(hour,dob,getdate())/8766.0,0)) as Age,
U.SocialId,
U.Gender,
U.Email,
isnull(U.IsProfileImageSync,0) IsProfileImageSync,
U.HomeTownCity,
U.ImageName,
isnull(fr.IsFriend,0) as IsFriend,
isnull(fr.IsRequestSent,0) as IsRequestSent,
isnull(fr.RequestSender,cast(cast(0 as binary) as uniqueidentifier)) as RequestSender,
isnull(fr.IsBlocked,0) as IsBlocked,
isnull(fr.FriendBlocked,0) as FriendBlocked,
[dbo].[fnCalcDistanceKM](cast(#StartLatitude1 as float),cast(#StartLongitude1 as float),cast (isnull(USRSHTOUT.Latitude,0) as float) ,cast(isnull(USRSHTOUT.Longitude,0) as float)) as Distance,
(geography::Point(coalesce(USRSHTOUT.Latitude,0), coalesce(USRSHTOUT.Longitude,0), 4326).STDistance(geography::Point(#StartLatitude1, #StartLongitude1, 4326))/1000) as DistanceTemp,
ULAL.UpdatedOn as LastActiveDateTime,
0 as InterestId,
'' as InterestName,
isnull(USRSHTOUT.ImageName,'') 'ShoutoutImageName',
isnull(USRSHTOUT.Description,'') Description,USRSHTOUT.CreatedOn,IsImageSync,
isnull(format(UGL.UpdatedOn,'dd-MMM, yyyy HH:mm tt'),'') 'DisplayUpdatedOn',
isnull(ADC.locality,'')[ShoutoutCity],
isnull(ADC.country,'')[ShoutoutCountry],
isnull(ADC.administrative_area_level_1,'') [AdministrativeAreaLevel1],
isnull(ADC.place_id,'') [PlaceId],
isnull(ADC.formatted_address,'') FormattedAaddress,
isnull(ADC.url,'') Url,
isnull(lt.TotalLike, 0) as TotalLike,
isnull(ct.TotalComment, 0) as TotalComment,
isnull(lt.SelfLike, 0) as SelfLike,
SHT.ShoutoutTypeId,
isnull(SHT.Name,'') ShoutoutType,
UPT.PostTypeId,
isnull(UPT.Name,'') PostTypeName,
USRSHTOUT.oldMoment,
UGL.Latitude 'UserLatitude',
UGL.Longitude 'UserLongitude',
USRSHTOUT.Latitude 'ShoutoutLatitude',
USRSHTOUT.Longitude 'ShoutoutLongitude',
DistanceShoutoutMiles
from
Users U
inner join UserShoutouts USRSHTOUT on U.UserId=USRSHTOUT.UserId
left join UserLastActivityLog ULAL on ULAL.UserId=U.UserId
left join UserGeoLocation UGL on UGL.UserId=U.UserId
left join AddressShoutoutMapping ASMP on ASMP.ShoutoutId=USRSHTOUT.ShoutoutId
left join AddressComponents ADC on ADC.AddressComponentId=ASMP.AddressComponentId
left join [ShoutoutType] SHT on SHT.ShoutoutTypeId=isnull(USRSHTOUT.ShoutoutTypeId,0)
LEFT JOIN [UserPostType] UPT ON UPT.PostTypeId = ISNULL(USRSHTOUT.PostTypeId,0)
cross apply (select cos(radians(#StartLatitude1)) * cos(radians(USRSHTOUT.Latitude)) * cos(radians(USRSHTOUT.Longitude) - radians(#StartLongitude1)) + sin(radians(#StartLatitude1)) * sin(radians(USRSHTOUT.Latitude))) T(ACosInput)
cross apply (select ((3959 * acos(case when abs(ACosInput) > 1 then sign(ACosInput)*1 else ACosInput end)))) T2(DistanceShoutoutMiles)
left join (
select ItemId,
count(1) TotalLike,
cast(sum(case when UserId = #anotherUserid then 1 else 0 end) as bit) as SelfLike
from dbo.LikeDetails
where Liked=1 and LikeSourceId=1
group by ItemId) as lt on USRSHTOUT.ShoutoutId = lt.ItemId
left join (
select ParentId,
count(1) as TotalComment
from Comments
where CommentSourceId=1 and Comments.IsDeleted=0
group by ParentId) as ct on USRSHTOUT.ShoutoutId = ct.ParentId
left join dbo.tvf_GetFriendsByUserId (#UserId) fr on u.UserId = fr.ThisFriendId
left join UserShoutoutsPrivate USP on USP.ShoutoutId = USRSHTOUT.ShoutoutId
left join UserInterest UI on UI.InterestId = USP.GroupId
left join Interest INTRST on INTRST.Id = UI.InterestId
where
USRSHTOUT.IsDeleted=0
and (((#oldMoment = 0) and USRSHTOUT.oldMoment = #oldMoment)
or ((#oldMoment = 1) and USRSHTOUT.oldMoment = 1 or USRSHTOUT.oldMoment = 0) )
and U.IsEmailVerified=1 and isnull(U.IsDeactivated,0)=0
and (#ShoutoutTypeId=0 or USRSHTOUT.ShoutoutTypeId=#ShoutoutTypeId)
and (#IsMyShoutout=0 or (#IsMyShoutout=1 and USRSHTOUT.UserId = #UserId))
and ((#UserName is not null and #UserName='all'
OR ((U.FirstName + ' ' + U.LastName) = #UserName)OR (U.FirstName like LTRIM(RTRIM(#UserName))+'%') OR (U.LastName like LTRIM(RTRIM(#UserName))+'%'))
OR ( #FirstName is not null AND #LastName is null and
((U.FirstName = #FirstName ) OR (U.FirstName like LTRIM(RTRIM(#FirstName))+'%')))
OR ( #LastName is not null AND #FirstName is null and
((U.LastName = #LastName ) OR (U.LastName like LTRIM(RTRIM(#LastName))+'%')))
OR ((( #FirstName is not null AND #LastName is not null AND
((U.FirstName + ' ' + U.LastName) = #FirstName + ' ' + #LastName) OR (U.FirstName like LTRIM(RTRIM(#FirstName))+'%')) and (U.LastName like LTRIM(RTRIM(#LastName))+'%'))))
and((#Interest <>'' AND #IsPrivate = 1 AND (exists (select * from dbo.UserInterest where (UserId = U.UserId and InterestId in (select * from dbo.Split(#Interest,','))))
or #Interest ='')
or(#IsPrivate = 1
and (UI.Interestid in (select items from dbo.Split(#GroupId,',')) and INTRST.IsPrivate = 1 and INTRST.IsDelete = 0 and USRSHTOUT.IsDeleted=0 and
USP.ShoutoutId = USRSHTOUT.ShoutoutId and UI.IsActive = 1 and USP.GroupId in (select items from dbo.Split(#GroupId,','))))
)
OR(#Interest <>'' AND #IsPrivate = 0 AND (exists (select * from dbo.UserInterest where (UserId = U.UserId and InterestId in (select * from dbo.Split(#Interest,','))))
or #Interest ='')
or(#IsPrivate = 1
and (UI.Interestid in (select items from dbo.Split(#GroupId,',')) and INTRST.IsPrivate = 1 and INTRST.IsDelete = 0 and USRSHTOUT.IsDeleted=0 and
USP.ShoutoutId = USRSHTOUT.ShoutoutId and UI.IsActive = 1 and USP.GroupId in (select items from dbo.Split(#GroupId,','))))
)
OR(#Interest ='' AND #IsPrivate = 0 AND (exists (select * from dbo.UserInterest where (UserId = U.UserId and InterestId in (select * from dbo.Split(#Interest,','))))
or #Interest =''))
)
and (#PostTypeId=0 or USRSHTOUT.PostTypeId=#PostTypeId)
)
insert into #UserList
select
UserId,
FirstName,
LastName,
QuickBloxId,
SocialId,
Gender,
Email,
IsProfileImageSync,
IsFriend,
IsRequestSent,
RequestSender,
IsBlocked,
FriendBlocked,
Age,
HomeTownCity,
ImageName,
Distance,
DistanceTemp,
LastActiveDateTime,
ShoutoutGuid,
ShoutoutId,
InterestId,
InterestName,
ShoutoutImageName,
Description,
CreatedOn,
IsImageSync,
DisplayUpdatedOn,
ShoutoutCity,
ShoutoutCountry,
AdministrativeAreaLevel1,
PlaceId,
FormattedAaddress,
Url,
u.TotalLike,
u.TotalComment,
u.Selflike,
ShoutoutTypeId,
ShoutoutType,
PostTypeId,
PostTypeName,
oldMoment,
UserLatitude,
UserLongitude,
ShoutoutLatitude,
ShoutoutLongitude,
DistanceShoutoutMiles
from UserList u
where
(#Gender ='' or ((Gender in(select * from dbo.Split(#Gender,','))) or (#Gender like '%3%' and Gender=0)))
and(
((#AgeFrom = 18) AND ((#AgeTo= 65 and Age >= 15 )
or (Age >= 15 and Age <= #AgeTo)))
OR
((#AgeTo= 65 and Age >= #AgeFrom )
or (Age >= #AgeFrom and Age <= #AgeTo))
)
and IsBlocked <> 1
and FriendBlocked <> 1
and (#Location=0 or ((DistanceShoutoutMiles<= #Radius) or (#IsLocal=1 and HomeTownCity=#HomeTownCity)))
and (#IsFriend=0 or (#IsFriend=1 and IsFriend=1))
and (#Location=0 or (
((#IsTraveler=1 and #IsLocal=1) or (#IsTraveler=0 and #IsLocal=0)) or
((#IsTraveler=1 and #IsLocal=0 and lower(HomeTownCity) != lower(#HomeTownCity))
or (#IsTraveler=0 and #IsLocal=1 and lower(HomeTownCity) = lower(#HomeTownCity)))))OPTION(RECOMPILE)
set #TotalRows = ##rowcount
IF(#CurrentPage=0)
begin
select * from #UserList order by Distance asc OPTION(OPTIMIZE FOR UNKNOWN)
end
ELSE
BEGIN
declare #OffSetSize as bigint
set #OffSetSize = ((#CurrentPage * #PageSize) - #PageSize)
IF (#SortExpression = '1')
BEGIN
SELECT *
FROM #UserList
WHERE CreatedOn<#CreatedDate
ORDER BY CreatedOn DESC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
ELSE IF (#SortExpression = '2')
BEGIN
SELECT *
FROM #UserList
WHERE CreatedOn>#CreatedDate
ORDER BY CreatedOn DESC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
ELSE IF (#SortExpression = '3')
BEGIN
SELECT *
FROM #UserList
ORDER BY Distance ASC, CreatedOn DESC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
ELSE IF (#SortExpression = '4')
BEGIN
SELECT *
FROM #UserList
ORDER BY Distance ASC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
ELSE
BEGIN
SELECT *
FROM #UserList
ORDER BY CreatedOn DESC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
END
ENDGO

Select columns without group by in aggregate

I'm using SQL Server 2014. I have a structure like this:
Id BIGINT,
ItemName NVARCHAR(4000),
RecordDate DATETIME2,
Supplier NVARCHAR(450),
Quantity DECIMAL(18, 2),
ItemUnit NVARCHAR(2000),
EntityUnit NVARCHAR(2000),
ItemSize DECIMAL(18, 2),
PackageSize DECIMAL(18, 2),
FamilyCode NVARCHAR(20),
Family NVARCHAR(500),
CategoryCode NVARCHAR(20),
Category NVARCHAR(500),
SubCategoryCode NVARCHAR(20),
SubCategory NVARCHAR(500),
ItemGroupCode NVARCHAR(20),
ItemGroup NVARCHAR(500),
PurchaseValue DECIMAL(18, 2),
UnitPurchaseValue DECIMAL(18, 2),
PackagePurchaseValue DECIMAL(18, 2),
FacilityCode NVARCHAR(450),
CurrencyCode NVARCHAR(5)
I'd like to select distinct ItemNames from BatchRecords table paired with the max Id among the items with the same ItemName as well as Supplier, Quantity and other values of the item with the max Id for each ItemName. So far, I came up with the following SP, definitely it doesn't work yet as GROUP BY throws an error.
I could probably use a subquery, but then how do I satisfy the condition with max Ids for each unique ItemName? Also, any input to the stored procedure quality/obvious bottleneck is highly appreciated as it has to be somewhat quick.
CREATE PROCEDURE dbo.GetRecordsPageFlat
(#BatchIds dbo.GenericIntArray READONLY,
#FileRequestId INT,
#PageSize INT,
#PageCount INT,
#LastId BIGINT,
#NameMaskValue NVARCHAR(128) = NULL,
#NameMaskType INT = NULL,
#FamilyCodeMaskValue NVARCHAR(128),
#CategoryCodeMaskValue NVARCHAR(128),
#SubCategoryCodeMaskValue NVARCHAR(128)
)
AS
SET NOCOUNT ON;
DECLARE #Temp dbo.RecordImportStructure
DECLARE #ErrorCode INT
DECLARE #Step NVARCHAR(200)
DECLARE #Rows INT
--OUTPUT ##ROWCOUNT
--OUTPUT INSERTED.Id
INSERT INTO #Temp (
Id,
ItemName,
Supplier,
Quantity,
ItemUnit,
EntityUnit,
ItemSize,
PackageSize,
PurchaseValue,
UnitPurchaseValue,
PackagePurchaseValue,
CurrencyCode
)
SELECT
BR.Id,
BR.ItemName,
BR.Supplier,
BR.Quantity,
BR.ItemUnit,
BR.EntityUnit,
BR.ItemSize,
BR.PackageSize,
BR.ItemGroup,
BR.UnitPurchaseValue,
BR.PackagePurchaseValue,
C.IsoCode
FROM
dbo.BatchRecords BR
LEFT OUTER JOIN
dbo.FacilityInstances F ON F.Id = BR.FacilityInstanceId
LEFT OUTER JOIN
dbo.Currencies C ON C.Id = BR.CurrencyId
--OPTION(RECOMPILE)
WHERE
BR.DataBatchId IN (SELECT * FROM #BatchIds)
AND BR.Id > #LastId
AND (#FamilyCodeMaskValue IS NULL OR BR.FamilyCode = #FamilyCodeMaskValue)
AND (#CategoryCodeMaskValue IS NULL OR BR.CategoryCode = #CategoryCodeMaskValue)
AND (#SubCategoryCodeMaskValue IS NULL OR BR.SubCategoryCode = #SubCategoryCodeMaskValue)
AND (#NameMaskType IS NULL AND #NameMaskValue IS NULL
OR ((#NameMaskType = 1 AND BR.ItemName LIKE #NameMaskValue + '%')
OR (#NameMaskType = 2 AND BR.ItemName LIKE '%' + #NameMaskValue)
OR (#NameMaskType = 3 AND BR.ItemName LIKE '%' + #NameMaskValue + '%')
))
GROUP BY
BR.ItemName
ORDER BY
BR.Id
OFFSET #PageCount * #PageSize ROWS
FETCH NEXT #PageSize ROWS ONLY;
UPDATE dbo.BatchActionRequests
SET PageNumber = #PageCount+1,
LatestItemId = (SELECT MAX(Id) FROM #Temp)
WHERE Id = #FileRequestId
It looks like a top-n-per-group problem.
There are two common approaches to it: using ROW_NUMBER and CROSS APPLY. Here is the ROW_NUMBER variant. See Get top 1 row of each group for details.
WITH
CTE
AS
(
SELECT
BR.Id,
BR.ItemName,
BR.Supplier,
BR.Quantity,
BR.ItemUnit,
BR.EntityUnit,
BR.ItemSize,
BR.PackageSize,
-- BR.ItemGroup,???
BR.UnitPurchaseValue,
BR.PackagePurchaseValue,
C.IsoCode AS CurrencyCode,
ROW_NUMBER() OVER (PARTITION BY BR.ItemName ORDER BY BR.Id DESC) AS rn
FROM
dbo.BatchRecords BR
LEFT OUTER JOIN dbo.FacilityInstances F ON F.Id = BR.FacilityInstanceId
LEFT OUTER JOIN dbo.Currencies C ON C.Id = BR.CurrencyId
WHERE
BR.DataBatchId IN (SELECT * FROM #BatchIds)
AND BR.Id > #LastId
AND (#FamilyCodeMaskValue IS NULL OR BR.FamilyCode = #FamilyCodeMaskValue)
AND (#CategoryCodeMaskValue IS NULL OR BR.CategoryCode = #CategoryCodeMaskValue)
AND (#SubCategoryCodeMaskValue IS NULL OR BR.SubCategoryCode = #SubCategoryCodeMaskValue)
AND (#NameMaskType IS NULL AND #NameMaskValue IS NULL
OR ((#NameMaskType = 1 AND BR.ItemName LIKE #NameMaskValue + '%')
OR (#NameMaskType = 2 AND BR.ItemName LIKE '%' + #NameMaskValue)
OR (#NameMaskType = 3 AND BR.ItemName LIKE '%' + #NameMaskValue + '%')
))
)
INSERT INTO #Temp (
Id,
ItemName,
Supplier,
Quantity,
ItemUnit,
EntityUnit,
ItemSize,
PackageSize,
-- PurchaseValue,???
UnitPurchaseValue,
PackagePurchaseValue,
CurrencyCode
)
SELECT
Id,
ItemName,
Supplier,
Quantity,
ItemUnit,
EntityUnit,
ItemSize,
PackageSize,
-- PurchaseValue,???
UnitPurchaseValue,
PackagePurchaseValue,
CurrencyCode
FROM CTE
WHERE rn = 1
ORDER BY
Id
OFFSET #PageCount * #PageSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(RECOMPILE);
For each ItemName the query will pick the row with the largest Id.
;WITH CTC
AS
(
SELECT MAX(BR.ID) AS Id, BR.ItemName
FROM dbo.BatchRecords BR
LEFT OUTER JOIN dbo.FacilityInstances F ON F.Id = BR.FacilityInstanceId
WHERE BR.DataBatchId IN (SELECT * FROM #BatchIds)
AND BR.Id > #LastId
AND (#FamilyCodeMaskValue IS NULL OR BR.FamilyCode = #FamilyCodeMaskValue)
AND (#CategoryCodeMaskValue IS NULL OR BR.CategoryCode = #CategoryCodeMaskValue)
AND (#SubCategoryCodeMaskValue IS NULL OR BR.SubCategoryCode = #SubCategoryCodeMaskValue)
AND (#NameMaskType IS NULL AND #NameMaskValue IS NULL
OR ((#NameMaskType = 1 AND BR.ItemName LIKE #NameMaskValue + '%')
OR (#NameMaskType = 2 AND BR.ItemName LIKE '%' + #NameMaskValue)
OR (#NameMaskType = 3 AND BR.ItemName LIKE '%' + #NameMaskValue + '%')
))
GROUP BY
BR.ItemName
)
INSERT INTO #Temp (
Id,
ItemName,
Supplier,
Quantity,
ItemUnit,
EntityUnit,
ItemSize,
PackageSize,
PurchaseValue,
UnitPurchaseValue,
PackagePurchaseValue,
CurrencyCode
)
SELECT BR.Id,
BR.ItemName,
BR.Supplier,
BR.Quantity,
BR.ItemUnit,
BR.EntityUnit,
BR.ItemSize,
BR.PackageSize,
BR.ItemGroup,
BR.UnitPurchaseValue,
BR.PackagePurchaseValue,
C.IsoCode
FROM CTC t
JOIN dbo.BatchRecords BR ON t.Id = BR.Id
LEFT OUTER JOIN dbo.Currencies C ON C.Id = BR.CurrencyId
ORDER BY BR.Id
OFFSET #PageCount * #PageSize ROWS
FETCH NEXT #PageSize ROWS ONLY;

sql select into select in function

When I try to alter the function below I get the following error message:
Only one expression can be specified in the select list when the
subquery is not introduced with EXISTS.
I guess it is probably because of select into select. But why does this select into select work separately ( not in function ) but not in function.
ALTER FUNCTION [dbo].[Getcurrentexchangerate] (#CurrencyFromId INT,
#CurrencyToId INT)
returns DECIMAL(13, 10)
AS
BEGIN
DECLARE #rate DECIMAL (13, 10)
DECLARE #dw INT
SET #dw = (SELECT Datepart(dw, Getdate()))
IF( #dw != 2 ) -- Monday
BEGIN
SET #rate = (SELECT TOP (1) [rate]
FROM currencyconversionrate
WHERE [currencyfromid] = #CurrencyFromId
AND [currencytoid] = #CurrencyToId
ORDER BY id DESC)
END
ELSE
BEGIN
SET #rate = (SELECT *
FROM (SELECT TOP(2) Row_number()
OVER (
ORDER BY id DESC) AS
rownumber,
rate
FROM currencyconversionrate
WHERE ( [currencyfromid] = 2
AND [currencytoid] = 5 )
ORDER BY id DESC) AS Rate
WHERE rownumber = 2)
END
IF( #rate IS NULL )
BEGIN
SET #rate = 1
END
RETURN #rate
END
See your "else" part
SET #rate = (SELECT *
FROM (SELECT TOP(2) Row_number()
OVER (
ORDER BY id DESC) AS
rownumber,
rate
FROM currencyconversionrate
WHERE ( [currencyfromid] = 2
AND [currencytoid] = 5 )
ORDER BY id DESC) AS Rate
WHERE rownumber = 2)
You're trying to select all fields from currencyconversionrate table, you can't do that, or do you want to select "RATE" column only?
Try changing to below:
SET #rate = (SELECT rate
FROM (SELECT TOP(1) Row_number()
OVER (
ORDER BY id DESC) AS
rownumber,
rate
FROM currencyconversionrate
WHERE ( [currencyfromid] = 2
AND [currencytoid] = 5 )
ORDER BY id DESC) AS Rate
WHERE rownumber = 2)

Stored Procedure and output parameter from paging script (SQL Server 2008)

I have the below stored procedure and would like to only have one SQL statement. At the moment you can see there are two statements, one for the actual paging and one for a count of the total records which needs to be return to my app for paging.
However, the below is inefficient as I am getting the total rows from the first query:
COUNT(*) OVER(PARTITION BY 1) as TotalRows
How can I set TotalRows as my output parameter?
ALTER PROCEDURE [dbo].[Nop_LoadAllOptimized]
(
#PageSize int = null,
#PageNumber int = null,
#WarehouseCombinationID int = null,
#CategoryId int = null,
#OrderBy int = null,
#TotalRecords int = null OUTPUT
)
AS
BEGIN
WITH Paging AS (
SELECT rn = (ROW_NUMBER() OVER (
ORDER BY
CASE WHEN #OrderBy = 0 AND #CategoryID IS NOT NULL AND #CategoryID > 0
THEN pcm.DisplayOrder END ASC,
CASE WHEN #OrderBy = 0
THEN p.[Name] END ASC,
CASE WHEN #OrderBy = 5
THEN p.[Name] END ASC,
CASE WHEN #OrderBy = 10
THEN wpv.Price END ASC,
CASE WHEN #OrderBy = 15
THEN wpv.Price END DESC,
CASE WHEN #OrderBy = 20
THEN wpv.Price END DESC,
CASE WHEN #OrderBy = 25
THEN wpv.UnitPrice END ASC
)),COUNT(*) OVER(PARTITION BY 1) as TotalRows, p.*, pcm.DisplayOrder, wpv.Price, wpv.UnitPrice FROM Nop_Product p
INNER JOIN Nop_Product_Category_Mapping pcm ON p.ProductID=pcm.ProductID
INNER JOIN Nop_ProductVariant pv ON p.ProductID = pv.ProductID
INNER JOIN Nop_ProductVariant_Warehouse_Mapping wpv ON pv.ProductVariantID = wpv.ProductVariantID
WHERE pcm.CategoryID = #CategoryId
AND (wpv.Published = 1 AND pv.Published = 1 AND p.Published = 1 AND p.Deleted = 0 AND pv.Deleted = 0 and wpv.Deleted = 0)
AND wpv.WarehouseID IN (select WarehouseID from Nop_WarehouseCombination where UserWarehouseCombinationID = #WarehouseCombinationID)
)
SELECT TOP (#PageSize) * FROM Paging PG
WHERE PG.rn > (#PageNumber * #PageSize) - #PageSize
SELECT #TotalRecords = COUNT(p.ProductId) FROM Nop_Product p
INNER JOIN Nop_Product_Category_Mapping pcm ON p.ProductID=pcm.ProductID
INNER JOIN Nop_ProductVariant pv ON p.ProductID = pv.ProductID
INNER JOIN Nop_ProductVariant_Warehouse_Mapping wpv ON pv.ProductVariantID = wpv.ProductVariantID
WHERE pcm.CategoryID = #CategoryId
AND (wpv.Published = 1 AND pv.Published = 1 AND p.Published = 1 AND p.Deleted = 0 AND pv.Deleted = 0 and wpv.Deleted = 0)
AND wpv.WarehouseID IN (select WarehouseID from Nop_WarehouseCombination where UserWarehouseCombinationID = #WarehouseCombinationID)
END
I think I understand your issue here. Have you considered that the Count could be done BEFORE the CTE
and then passed in as value to the CTE as a variable.
i.e, set the value for #TotalRecords up front, pass it in, and so the CTE will use this count rather than executing the count a second time?
Does this make sense, or have I missed your point here.
no problem friend, highly possible i missed a trick here. However without the schema and data its tricky to test what I am suggesting. In the absence of someone giving a better answer, I've put this test script with data together to demo what I am talking about. If this isn't what you want then no problem. If it is just plain missing the point again, then I'll take that on the chin.
Declare #pagesize as int
Declare #PageNumber as int
Declare #TotalRowsOutputParm as int
SET #pagesize = 3
SET #PageNumber = 2;
--create some test data
DECLARE #SomeData table
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[SomeValue] [nchar](10) NULL
)
INSERT INTO #SomeData VALUES ('TEST1')
INSERT INTO #SomeData VALUES ('TEST2')
INSERT INTO #SomeData VALUES ('TEST3')
INSERT INTO #SomeData VALUES ('TEST4')
INSERT INTO #SomeData VALUES ('TEST5')
INSERT INTO #SomeData VALUES ('TEST6')
INSERT INTO #SomeData VALUES ('TEST7')
INSERT INTO #SomeData VALUES ('TEST8')
INSERT INTO #SomeData VALUES ('TEST9')
INSERT INTO #SomeData VALUES ('TEST10');
--Get total count of all rows
Set #TotalRowsOutputParm = (SELECT COUNT(SomeValue) FROM #SomeData p) ;
WITH Paging AS
(
SELECT rn = (ROW_NUMBER() OVER (ORDER BY SomeValue ASC)),
#TotalRowsOutputParm as TotalRows, p.*
FROM [SomeData] p
)
SELECT TOP (#PageSize) * FROM Paging PG
WHERE PG.rn > (#PageNumber * #PageSize) - #PageSize
PRINT #TotalRowsOutputParm
I don't think you can do it without running the query twice if you want to assign it to a variable
however, can't you just add another column and do something like this instead?
;WITH Paging AS (select *,ROW_NUMBER() OVER(ORDER BY name) AS rn FROM sysobjects)
SELECT (SELECT MAX(rn) FROM Paging) AS TotalRecords,* FROM Paging
WHERE rn < 10
Or in your case
SELECT TOP (#PageSize) *,(SELECT MAX(PG.rn) FROM Paging) AS TotalRecords
FROM Paging PG
WHERE PG.rn > (#PageNumber * #PageSize) - #PageSize
Then from the front end grab that column
In the end I decided just to use two different SQL statements, one for count, one for select.
The "COUNT(*) OVER(PARTITION BY 1) as TotalRows" actually was pretty expensive and it turned out much quicker to just use two different statements.
Thank you everyone who helped with this question.