Sql query has low performance on SQL server management studio - sql

I hope this year will be great.
I am new to SQL server and i'm trying to display some values with the lower cost. At now, the query gives me the results in almost 17 seconds. I would like to have performance almost 8 to 5 seconds.
This is a query to display data on a graph. I take this query and I insert it into a php file.
I have created indexes so I have succeed from 25 seconds to 17 seconds. I don't know what to do next.
Here is my code:
DECLARE #jahre TABLE(jahr int);
WITH CTE AS
(
SELECT 2013 AS JournalDatum
UNION ALL
SELECT JournalDatum+1
FROM CTE
WHERE JournalDatum < YEAR(GETDATE())
)
INSERT INTO #jahre SELECT * FROM CTE
DECLARE #years4Pivot AS NVARCHAR(MAX),#query AS NVARCHAR(MAX)
SET #years4Pivot = STUFF((SELECT ',' + '['+CAST(jahr AS VARCHAR(4))+ ']' FROM #jahre FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #query = N'
WITH cashin AS (
SELECT * FROM (
SELECT
/*
dbo.cdGetFDOM(JournalDatum) myDatum
,MONTH(JournalDatum) AS Monat
,jou.KreisLFN
*/
DATENAME(YEAR, JournalDatum) AS Jahr
,jou.ObjektLFN
,CAST(SUM(FibuHabenNetto) as float)-CAST(SUM(FibuSollNetto) as float)-CAST(SUM(FibuMWST) as float) fibuBetrag
,(''NKM_'' + REPLACE(SUBSTRING(EinheitArtBezeichnung,2,2),'')'','''')) EinhArtPos
,mieteig.MietEigLFN
,mieteig.MietEigCode1
FROM
dbo.TF0700_Journal AS jou
JOIN dbo.TF0720_Fibu AS fibu ON fibu.JournalLFN = jou.JournalLFN
JOIN dbo.TF0710_JournalOPPos AS joupos ON joupos.OpPosLFN = fibu.OPPosLFN
JOIN dbo.TA0270_Position AS pos ON pos.PositionLFN = joupos.PositionLFN
JOIN dbo.TA0310_MietEigEinheit ME ON ME.EinheitLFN = joupos.EinheitLFN
JOIN dbo.TZ0310_EinheitArt EA ON ME.EinheitArtLFN = EA.EinheitArtLFN
JOIN dbo.TA0300_MietEig mieteig ON joupos.MietEigLFN = mieteig.MietEigLFN
WHERE
JournalArt = 21
AND pos.PositionArt=1
AND RIGHT(LEFT(MietEigCode1,5),1) NOT IN
(
SELECT MietEigCode1 from TA0300_MietEig
WHERE RIGHT(LEFT(MietEigCode1,5),1) IS NOT NULL
AND RIGHT(LEFT(MietEigCode1,5),1) NOT LIKE '' ''
)
GROUP BY
/*
dbo.cdGetFDOM(JournalDatum) myDatum
,MONTH(JournalDatum) AS Monat
,jou.KreisLFN
*/
DATENAME(YEAR, JournalDatum)
,jou.ObjektLFN
,REPLACE(SUBSTRING(EinheitArtBezeichnung,2,2),'')'','''')
,mieteig.MietEigLFN
,mieteig.MietEigCode1
) AS Q
PIVOT (SUM(fibuBetrag) FOR EinhArtPos IN (NKM_W,NKM_G,NKM_B,NKM_GA,NKM_SP,NKM_S)) P
)
SELECT *
FROM
(
SELECT
/*
--c.myDatum
--,c.Monat
--,c.KreisLFN
*/
c.Jahr as Jahr
,c.ObjektLFN
,ISNULL(NKM_W,0)+ISNULL(NKM_G,0)+ISNULL(NKM_B,0)+ISNULL(NKM_GA,0)+ISNULL(NKM_SP,0)+ISNULL(NKM_S,0) AS Nettokaltmiete
,obj.ObjektBezeichnung
FROM cashin c
LEFT JOIN dbo.TA0200_Objekt obj ON c.ObjektLFN=obj.ObjektLFN
WHERE DOMUS4000_MIRROR_1.dbo.cdIsValidImDatum(GETDATE(),3,obj.ObjektLFN)>0
) tbl1
PIVOT (
SUM(Nettokaltmiete)
FOR Jahr IN (' + #years4Pivot + N')
) pvt
ORDER BY ObjektBezeichnung ASC '
exec sp_executesql #query;
and the screenshots of execution plan:
Here is the link for a better looking :)
https://www.brentozar.com/pastetheplan/?id=HkSEjV7Av
Also the code for the function cdIsValidImDatum is here:
USE [DOMUS4000_MIRROR_1]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-------------------------------------------------------------------------------------------------------------------------------
ALTER FUNCTION [dbo].[cdIsValidImDatum](#bDate DATE, #bLevel int,#lfn int) RETURNS INT
AS
BEGIN
DECLARE #tmpInt INT
/*
#bLevel
1: Mandant
2: Kreis
3: Objekt
4: Einheit
*/
IF #bDate IS NULL OR #bLevel IS NULL OR #lfn IS NULL
BEGIN
SET #tmpInt = 0
END
ELSE
BEGIN
IF #bLevel = 4
BEGIN
SET #tmpInt =
(
SELECT
COUNT(*)
FROM
dbo.TA0310_MietEigEinheit AS einh LEFT JOIN
dbo.TA0200_Objekt AS obj ON einh.ObjektLFN = obj.ObjektLFN LEFT JOIN
dbo.TA0100_Kreis AS kre ON obj.KreisLFN = kre.KreisLFN LEFT JOIN
dbo.TA0010_Mandant AS man ON kre.MandantLFN = man.MandantLFN
WHERE
LEFT(ISNULL(man.MandantCode, ''), 1) <> '0'
AND
RIGHT(LEFT(ISNULL(man.MandantCode, ''), 3),1) <> '1'
AND
(man.MandantBeginn <= #bDate OR man.MandantBeginn IS NULL)
AND
(man.MandantEnde >= #bDate OR man.MandantEnde IS NULL)
AND
LEFT(ISNULL(kre.KreisCode, ''), 1) <> '0'
AND
RIGHT(LEFT(ISNULL(obj.ObjektCode, ''), 2),1) <> '0'
AND
(obj.ObjektVerwaltungsbeginn <= #bDate OR obj.ObjektVerwaltungsbeginn IS NULL)
AND
(obj.ObjektVerwaltungsende >= #bDate OR obj.ObjektVerwaltungsende IS NULL)
AND
(einh.GueltigBis >= #bDate OR einh.GueltigBis IS NULL)
AND
(einh.EinheitErstbezug <= #bDate OR einh.EinheitErstbezug IS NULL)
AND einh.EinheitLFN=#lfn
)
END
ELSE IF #bLevel = 3
BEGIN
SET #tmpInt =
(
SELECT
COUNT(*)
FROM
dbo.TA0200_Objekt AS obj LEFT JOIN
dbo.TA0100_Kreis AS kre ON obj.KreisLFN = kre.KreisLFN LEFT JOIN
dbo.TA0010_Mandant AS man ON kre.MandantLFN = man.MandantLFN
WHERE
LEFT(ISNULL(man.MandantCode, ''), 1) <> '0'
AND
RIGHT(LEFT(ISNULL(man.MandantCode, ''), 3),1) <> '1'
AND
(man.MandantBeginn <= #bDate OR man.MandantBeginn IS NULL)
AND
(man.MandantEnde >= #bDate OR man.MandantEnde IS NULL)
AND
LEFT(ISNULL(kre.KreisCode, ''), 1) <> '0'
AND
RIGHT(LEFT(ISNULL(obj.ObjektCode, ''), 2),1) <> '0'
AND
(obj.ObjektVerwaltungsbeginn <= #bDate OR obj.ObjektVerwaltungsbeginn IS NULL)
AND
(obj.ObjektVerwaltungsende >= #bDate OR obj.ObjektVerwaltungsende IS NULL)
AND
obj.ObjektLFN=#lfn
)
END
ELSE IF #bLevel = 2
BEGIN
SET #tmpInt =
(
SELECT
COUNT(*)
FROM
dbo.TA0100_Kreis AS kre INNER JOIN
dbo.TA0010_Mandant AS man ON kre.MandantLFN = man.MandantLFN
WHERE
LEFT(ISNULL(man.MandantCode, ''), 1) <> '0'
AND
RIGHT(LEFT(ISNULL(man.MandantCode, ''), 3),1) <> '1'
AND
(man.MandantBeginn <= #bDate OR man.MandantBeginn IS NULL)
AND
(man.MandantEnde >= #bDate OR man.MandantEnde IS NULL)
AND
LEFT(ISNULL(kre.KreisCode, ''), 1) <> '0'
AND
kre.KreisLFN=#lfn
)
END
ELSE IF #bLevel = 1
BEGIN
SET #tmpInt =
(
SELECT
COUNT(*)
FROM
dbo.TA0010_Mandant AS man
WHERE
LEFT(ISNULL(man.MandantCode, ''), 1) <> '0'
AND
RIGHT(LEFT(ISNULL(man.MandantCode, ''), 3),1) <> '1'
AND
(man.MandantBeginn <= #bDate OR man.MandantBeginn IS NULL)
AND
(man.MandantEnde >= #bDate OR man.MandantEnde IS NULL)
AND
man.MandantLFN=#lfn
)
END
END
RETURN #tmpInt
END

Finally guys I found the solution. I dropped it down to 4 seconds. I did
LEFT JOIN in this
LEFT JOIN dbo.TA0300_MietEig mieteig ON joupos.MietEigLFN = mieteig.MietEigLFN
and in the WHERE section I fielded with this:
WHERE
JournalArt = 21
AND pos.PositionArt=1
AND RIGHT(LEFT(mieteig.MietEigCode1,5),1) IS NOT NULL
AND RIGHT(LEFT(MietEigCode1,5),1) LIKE '' ''
The results were the same.
If anyone has more accurate answer please do not hesitate to explain in this post.
Thanks again.

Related

I have a query that returns results but I want to delete the data inside the parenthesis like <#0077d3>

User code I used the code to display the results
SELECT ( ROW_NUMBER() OVER (ORDER BY c.[exp] DESC)) as [rank], c.[name],c.[lv],c.[exp],
`ISNULL(b.[name],'n/a') [guild],
ISNULL(b.[icon],'none.jpg') [guild_icon],
c.[job],
CAST(
CASE
WHEN c.[login_time] > c.[logout_time]
THEN 'ON'
ELSE 'OFF'
END
AS VARCHAR ) AS [stat] FROM [Telecaster].[dbo].[Character] c
LEFT JOIN [Telecaster].[dbo].[GuildMember] a ON [sid] = a.[player_id]
LEFT JOIN [Telecaster].[dbo].[Guild] b ON b.[sid] = a.[guild_id]`
WHERE c.[permission] < 100 AND c.[name] NOT LIKE '%#%' AND c.[lv] < 300
Actual results
desired results
I want to delete the color code along with the brackets
SELECT ( ROW_NUMBER() OVER (ORDER BY c.[exp] DESC)) as [rank], CASE WHEN (c.[name] LIKE '%<%' AND c.[name] LIKE '%>%') THEN RIGHT(c.[name],LEN(c.[name])-CHARINDEX('>',c.[name])) ELSE c.[name] END [name],c.[lv],c.[exp],
ISNULL(b.[name],'n/a') [guild],
ISNULL(b.[icon],'none.jpg') [guild_icon],
c.[job],
CAST(
CASE
WHEN c.[login_time] > c.[logout_time]
THEN 'ON'
ELSE 'OFF'
END
AS VARCHAR ) AS [stat] FROM [Telecaster].[dbo].[Character] c
LEFT JOIN [Telecaster].[dbo].[GuildMember] a ON [sid] = a.[player_id]
LEFT JOIN [Telecaster].[dbo].[Guild] b ON b.[sid] = a.[guild_id]
WHERE c.[permission] < 100 AND c.[name] NOT LIKE '%#%' AND c.[lv] < 300
I assumed the color String format would be similar across the records.
I would create a scalar function to remove the tags. Here's fiddle on how to do it. You could just do a STUFF in your original query but there's no error checking like you can do in a function.
CREATE FUNCTION fn_StripColorCode (#InputString nvarchar(512))
RETURNS nvarchar(512)
AS
BEGIN
DECLARE #first int = -1;
DECLARE #last int = -1;
--Find the start and end tags.
SET #first = CHARINDEX('<#', #InputString, 1);
SET #last = CHARINDEX('>', #InputString, 1);
--If either start or end is not found, return original string.
IF (#first < 0 OR #last < 0)
RETURN #InputString;
--If the start tag is found after the end tag, return the original string.
IF (#first > #last)
RETURN #InputString;
--Remove the tag.
DECLARE #result nvarchar(512);
SET #result = STUFF(#InputString, 1, #Last, '');
RETURN #result;
END
;
DECLARE #testName nvarchar(50) = '<#ff00c0>ASTA';
SELECT dbo.fn_StripColorCode(#testName);
(No column name)
ASTA
fiddle
Here's how I would do it inline using STUFF. I cleaned up your code a bit:
SELECT
ROW_NUMBER() OVER (ORDER BY c.[exp] DESC) as [rank]
, CASE
WHEN (c.[name] LIKE '<#%' AND c.[name] LIKE '%>%')
THEN STUFF(c.[name],1,CHARINDEX('>',c.[name]),'')
ELSE c.[name]
END [name]
, c.[lv]
, c.[exp]
, ISNULL(b.[name],'n/a') [guild]
, ISNULL(b.[icon],'none.jpg') [guild_icon]
, c.[job]
, CASE
WHEN c.[login_time] > c.[logout_time]
THEN 'ON'
ELSE 'OFF'
END AS [stat]
FROM [Telecaster].[dbo].[Character] c
LEFT JOIN [Telecaster].[dbo].[GuildMember] a
ON [sid] = a.[player_id]
LEFT JOIN [Telecaster].[dbo].[Guild] b
ON b.[sid] = a.[guild_id]
WHERE c.[permission] < 100
AND c.[name] NOT LIKE '%#%'
AND c.[lv] < 300

Offer to increase performance in stored procedure

I write this query in SQL Server 2016:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[s2_GetReceivedDocumentsCount]
#_Username NVARCHAR(MAX),
#_SearchText NVARCHAR(MAX),
#_States NVARCHAR(MAX),
#_Senders NVARCHAR(MAX),
#_Date1 NVARCHAR(MAX),
#_Date2 NVARCHAR(MAX),
#_Filter1ID NVARCHAR(MAX),
#_Filter1Value NVARCHAR(MAX)
AS
BEGIN
--https://blogs.technet.microsoft.com/mdegre/2011/11/06/what-is-parameter-sniffing/
DECLARE #Username NVARCHAR(MAX)
DECLARE #Fild BIT
DECLARE #SearchText NVARCHAR(MAX)
DECLARE #States NVARCHAR(MAX)
DECLARE #Senders NVARCHAR(MAX)
DECLARE #Date1 NVARCHAR(MAX)
DECLARE #Date2 NVARCHAR(MAX)
DECLARE #Filter1ID NVARCHAR(MAX)
DECLARE #Filter1Value NVARCHAR(MAX)
SELECT
#Username = #_Username,
#SearchText = #_SearchText,
#States = #_States,
#Senders = #_Senders,
#Date1 = #_Date1,
#Date2 = #_Date2,
#Filter1ID = #_Filter1ID,
#Filter1Value = #_Filter1Value
SELECT #SearchText = LTRIM(RTRIM(IsNull(#SearchText, '')))
SELECT #Filter1ID = LTRIM(RTRIM(IsNull(#Filter1ID, '')))
SELECT #Filter1Value = LTRIM(RTRIM(IsNull(#Filter1Value, '')))
DECLARE #PersonalPostID INT = NULL
SELECT #PersonalPostID = p.PostID
FROM Person pr
JOIN PersonPost pp ON pp.PersonID = pr.PersonID
JOIN Post p ON p.PostID = pp.PostID
WHERE pr.Username = #Username
AND p.IsPersonalPost = 1
DECLARE #independentPostExists BIT = CASE
WHEN EXISTS (SELECT 1 FROM Post t
WHERE t.Independent = 1 AND t.PostID > 0)
THEN 1
ELSE 0
END
DECLARE #temp0 TABLE (
DocumentID int
, Likeness int
, ParentScrutinyID int
)
;With AllPost
As
(
Select pp.PostID
From
PersonPost pp
Join Person prs On prs.PersonID = pp.PersonID
Where prs.Username = #Username
Union
Select [type].PostID
From
Post [type]
Join Post p On p.TypeID = [type].PostID
Join PersonPost pp On pp.PostID = p.PostID
Join Person prs On prs.PersonID = pp.PersonID
Where prs.Username = #Username
)
,
SplitSearchText
AS
(
Select * From dbo._1001_Split(dbo.ReplaceYK(#SearchText),N'')
),
Temp0
AS
(
Select Distinct
s.DocumentID
, s.Code
, s2_Scrutiny.ParentScrutinyID
From
s2_Document s
Join s2_State state On state.StateID = s.StateID
Join Post sender On sender.PostID = s.SenderID
Join s2_Scrutiny On
s2_Scrutiny.DocumentID = s.DocumentID
And s2_Scrutiny.IsActive = 1
And s2_Scrutiny.ReferenceID not in (-10, -20)
Cross Join AllPost
Join s2_Producer On s2_Producer.DocumentID = s.DocumentID
Join PersonPost producerPost On producerPost.PostID = s2_Producer.PostID
Join Person producerPerson On producerPerson.PersonID = producerPost.PersonID
Where
1 = 1
And (#States = '' Or (N',' + #States + N',') Like (N'%,' + Cast(s.StateID as nvarchar(max)) + ',%'))
And (#Senders = '' Or (N',' + #Senders + N',') Like (N'%,' + Cast(s.SenderID as nvarchar(max)) + ',%'))
And (#Date1 = '' Or s.RegistrationDate >= #Date1)
And (#Date2 = '' Or s.RegistrationDate <= #Date2)
And (#Filter1ID = ''
Or Exists(
Select 1
From
s2_FieldValue fv
Join s2_Field f On f.FieldID = fv.FieldID
Where
fv.DocumentID = s.DocumentID
And fv.FieldID = #Filter1ID
And (
(f.FieldTypeID in (0, 5/*فیلد محاسباتی*/) And fv.[Value] = #Filter1Value)
Or (f.FieldTypeID = 3 And Cast(fv.[FieldOptionID] as nvarchar(max)) = #Filter1Value)
Or (f.FieldTypeID in(1,2,4))
)
))
--پیشنهاد به پست یا نوع پستی که این شخص حائز آن است، ارجاع شده است
And AllPost.PostID = s2_Scrutiny.ReferenceID
), Temp1
AS
(
Select Distinct
s.DocumentID
,Likeness = 99999999
From Temp0 s
Where #SearchText != '' And #SearchText = ISNULL(s.Code, s.DocumentID)
Union
Select Distinct
s.DocumentID
,Likeness = SUM(ts.[Length])
From
Temp0 s
Join s2_TextSegment ts On
ts.TableName = N's2_Document'
And ts.FieldName = N'Subject'
And ts.RecordID = s.DocumentID
Where #SearchText != '' And #SearchText != ISNULL(s.Code, s.DocumentID)
Group by s.DocumentID
Union
Select Distinct
s.DocumentID
,Likeness = 1
From Temp0 s
Where #SearchText = ''
)
, Temp2
AS
(
Select t0.*, t1.Likeness
From
Temp0 t0
Join Temp1 t1 On t0.DocumentID = t1.DocumentID
)
Insert Into #temp0 (DocumentID, Likeness, ParentScrutinyID)
Select DocumentID, Likeness, ParentScrutinyID From Temp2
DECLARE #temp1 TABLE (
DocumentID int
, Likeness int
)
If #independentPostExists = 0
Begin
Insert Into #temp1 (DocumentID, Likeness)
Select
t.DocumentID
, t.Likeness
From
#temp0 t
End
ELSE
Begin--حوزه مستقلی تعریف شده باشد
--انتقال حوزه فعال باشد
Insert Into #temp1 (DocumentID, Likeness)
Select
t.DocumentID
, t.Likeness
From
#temp0 t
Join s2_Scrutiny parentScrutiny On parentScrutiny.ScrutinyID = t.ParentScrutinyID
Join s2_ScrutinyItem sci On sci.ScrutinyItemID = parentScrutiny.ScrutinyItemID
Where
sci.TransferArea = 1
-- شخص جاری در حوزه ارجاع دهنده باشد
Insert Into #temp1 (DocumentID, Likeness)
Select
t.DocumentID
, t.Likeness
From
#temp0 t
Join s2_Scrutiny parentScrutiny On parentScrutiny.ScrutinyID = t.ParentScrutinyID
Join Temp_SubalternPost tsp1 On tsp1.Subaltern_PostID = parentScrutiny.ScrutinierID
Join Temp_SubalternPost tsp2 On tsp2.Superior_PostID = tsp1.Superior_PostID
Where
tsp1.Superior_NearestIndependent = 1
And tsp2.Subaltern_PostID = #PersonalPostID
--And Not Exists(Select 1 From #temp0 tt Where tt.DocumentID = t.DocumentID)
End
Select Count(Distinct t.DocumentID) From #temp1 t Where Likeness > 0
END--end procedure
GO
This code takes 26 seconds:
exec sp_executesql N'Exec [dbo].[s2_GetReceivedDocumentsCount] #username=N'admin', #Filter1ID=N'12',#Filter1Value=N'17658'
BUT :
I tested this code for another state but returned 22,000 records in 3 seconds
exec sp_executesql N'Exec [dbo].[s2_GetReceivedDocumentsCount] #username=N'admin'
In this code I removed the #Filter1ID=N'12',#Filter1Value=N'17658'
When I remove this #Filter1ID it not enter here:
And (#Filter1ID = ''
Or Exists(
Select 1
From
s2_FieldValue fv
Join s2_Field f On f.FieldID = fv.FieldID
Where
fv.DocumentID = s.DocumentID
And fv.FieldID = #Filter1ID
And (
(f.FieldTypeID in (0, 5/*فیلد محاسباتی*/) And fv.[Value] = #Filter1Value)
Or (f.FieldTypeID = 3 And Cast(fv.[FieldOptionID] as nvarchar(max)) = #Filter1Value)
Or (f.FieldTypeID in(1,2,4))
)
))
Now I'm sure problem is here. But where is it? Where is the problem?
While correlated EXISTS clauses can be a real problem, your overall SP is such a dogs breakfast that I think you should focus on other aspects first:
Do not use LIKE to match a list of numeric values:
(N',' + #States + N',') Like (N'%,' + Cast(s.StateID as nvarchar(max)) + ',%'))
Since you already utilise string splitting function, you should split input value into a table variable of stateIDs (make sure that data type is the same as s.StateID and join it. Do the same for #Senders.
Minimise the use of OR as this kills performance really quickly:
This And (#Date1 = '' Or s.RegistrationDate >= #Date1) should be replaced by:
SET #Date1 = CASE WHEN '' THEN '01-Jan-1753' ELSE #Date1 END and then in your query you can simply have And s.RegistrationDate >= #Date1.
For #Date2 use the maximum value as per DATETIME reference.
Get rid of NVARCHAR( MAX ). Unless you realistically expect input values to be more than 4000 characters, you should use NVARCHAR( 2000 ) or something smaller.
There is a major performance difference between UNION and UNION ALL. Make sure you use UNION ALL unless you need to remove duplicate records. See this
And lastly EXISTS: without fully knowing your table structure and being able to run the query myself I cannot see a way of removing it, such that it will definitely improve performance.

Grouping within a While Loop, SQL Server

I've been building a while loop to populate a lot of data, and I'm struggling with grouping within the query - I want to add a group on Membership_Level but each time it is returning identical values (the total) for each Level.
Can anyone help me?
Thank you in advance!!!
DECLARE #Counter int
DECLARE #NumPerson int
SET #Counter = 1
WHILE #Counter <= 12
BEGIN
SET #NumPerson = (SELECT
SUM(Amount)
FROM [NewMember]
WHERE LEFT([PERIOD], 4) = 2016
AND GRADE_STATUS = 'N'
AND RIGHT([Period], 2) = #Counter)
SELECT
*
FROM (SELECT
CAST(#NumPerson AS varchar(6)) AS 'Number',
CASE
WHEN LEN(CAST(#Counter AS varchar(2))) = 1 THEN '0' + CAST(#Counter AS varchar(2))
ELSE CAST(#Counter AS varchar(2))
END AS 'Month') s
JOIN (SELECT
MAX('1') AS NGroup,
[PERIOD],
RIGHT([Period], 2) AS 'Month',
MEMBERSHIP_LEVEL
FROM [NewMember]
WHERE LEFT([PERIOD], 4) = 2016
AND GRADE_STATUS = 'N'
GROUP BY [MEMBERSHIP_LEVEL],
[PERIOD],
RIGHT([Period], 2)) t
ON s.[Month] = t.[Month]
SET #Counter = #Counter + 1
END

SQL: LEFT OUTER JOIN not returning any rows

I have a query that is using a LEFT OUTER JOIN to merge 2 data sets. I know both data sets should return data because I ran the superquery and the subquery separately. For some reason, the query is returning zero results. Anyone know why?
Left data:
item FG_lots
447845 E2211
Right data:
candy_lot_check candy_item
L2211 835116
Intended result:
item FG_lots candy_lot_check candy_item
447845 E2211 null null
The result from my broken query (no results):
item FG_lots candy_lot_check candy_item
The query:
--Initialization--
DECLARE #Item NVARCHAR(30) = '447845'
DECLARE #Date datetime = '6/13/2016'
SET DATEFIRST 1;
DECLARE #client NVARCHAR(20)
SET #client = (SELECT i.Uf_ClientName FROM item AS i WHERE i.item = #Item)
DECLARE #count integer
--Query--
SET #count = (CASE
WHEN (#client = 'A' OR #client = 'B')
THEN 4
WHEN #client = 'C'
THEN 3
WHEN #client = 'D'
THEN 5
ELSE
4
END)
SELECT DISTINCT
t.item,
LEFT(t.lot,#count) AS FG_lots,
(CASE
WHEN candylot.candy_lots IS NULL
THEN 'NO MATCH'
ELSE candylot.candy_lots
END) AS candy_lot_check,
(CASE
WHEN candylot.item IS NULL
THEN 'NO MATCH'
ELSE candylot.item
END) AS candy_item
FROM
ISW_LPTrans AS t
LEFT OUTER JOIN
(
SELECT
t.item,
LEFT(t.lot,#count) AS candy_lots,
t.ref_num AS job,
t.ref_line_suf AS suffix
FROM
ISW_LPTrans AS t
INNER JOIN item AS i on i.item = t.item
WHERE
i.product_code = 'RM-Candy' AND
t.trans_date = #Date AND
t.trans_type = 'I' AND
t.ref_num IN
(
SELECT TOP 1
j.job
FROM
job AS j
WHERE
j.item = #Item AND
j.job_date = (SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, #Date), #Date))
ORDER BY
j.job
)
AND t.ref_line_suf IN
(
SELECT TOP 1
j.suffix
FROM
job AS j
WHERE
j.item = #Item AND
j.job_date = (SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, #Date), #Date))
)
GROUP BY
t.item,
t.lot,
t.ref_num,
t.ref_line_suf
) AS candylot ON LEFT(t.lot, #count) = candylot.candy_lots
WHERE
t.ref_num = candylot.job AND
t.ref_line_suf = candylot.suffix AND
t.trans_type = 'F' AND
t.item = #Item AND
t.trans_date = #Date
You've got two 't' aliases, try altering it.
It seems you could rewrite it to make it more readable (joinwise, not indentwise), it could be that something's not right in the logic as well

Stored Procedure with join returning multiple records

I have the following stored procedure:
ALTER PROCEDURE [dbo].[stp_RandomisationResultCount]
#noOfRows INT,
#subcouncil INT,
#wards VARCHAR(MAX) = NULL,
#suburbs VARCHAR(MAX) = NULL,
#courts VARCHAR(MAX) = NULL,
#skills VARCHAR(MAX) = NULL,
#isDisabled VARCHAR(1) = NULL,
#hasQualification VARCHAR(1) = NULL,
#gender VARCHAR(1) = NULL,
#age INT = NULL
AS
BEGIN
SELECT
COUNT(tblJobSeekerDetails.JobSeeker_ID) resultCount
FROM
tblJobSeekerDetails
LEFT JOIN
tbl_lnk_JobSeeker_OtherSkills ON tblJobSeekerDetails.JobSeeker_ID = tbl_lnk_JobSeeker_OtherSkills.JobSeeker_ID
LEFT JOIN
tblOtherSkills ON tbl_lnk_JobSeeker_OtherSkills.OtherSkillsID = tblOtherSkills.OtherSkillsID
/*LEFT JOIN tblJobSeekerEmploymentHistory
ON tblJobSeekerDetails.JobSeeker_ID = tblJobSeekerEmploymentHistory.JobSeekerID*/
WHERE
(tblJobSeekerDetails.SubCouncilID = #subcouncil)
AND ((WardID IN (SELECT s.Item FROM ufn_SplitIntArray(#wards, ',') s)) OR (#wards IS NULL))
AND ((Suburb IN (SELECT s.Item FROM ufn_SplitIntArray(#suburbs, ',') s)) OR (#suburbs IS NULL))
AND ((RoadType IN (SELECT s.Item FROM ufn_SplitIntArray(#courts, ',') s)) OR (#courts IS NULL))
AND ((tblOtherSkills.OtherSkillsID in (SELECT s.Item FROM ufn_SplitIntArray(#skills, ',') s)) OR (#skills IS NULL))
AND ((Disability = #isDisabled) OR (#isDisabled IS NULL))
AND ((HasTertiaryQualification = #hasQualification) OR (#hasQualification IS NULL))
AND ((Gender = #gender) OR (#gender IS NULL))
AND ((ISNUMERIC(IdentityNumber) = 1 AND
IdentityNumber NOT LIKE '%.%' AND
DATEPART(YEAR, GETDATE()) - (CONVERT(INT, '19' + SUBSTRING(IdentityNumber, 1, 2), 100)) = #age) OR (#age IS NULL))
AND (TypeID = 1)--Jobseekers only
AND (tblJobSeekerDetails.IsExcludedFromRandomisation <> 1 OR tblJobSeekerDetails.IsExcludedFromRandomisation IS NULL)--Explicitly excluded jobseekers
AND (tblJobSeekerDetails.JobSeeker_ID not in (SELECT DISTINCT tj.JobSeeker_ID --Exclude Jobseekers as per stipulated exclusion periods
FROM tblJobSeekerDetails tj INNER JOIN tblJobSeekerEmploymentHistory wh
ON tj.JobSeeker_ID = wh.JobSeekerID
WHERE ((DATEDIFF(DAY, wh.DateOfEmploymentFrom, wh.DateOfEmploymentTo) <= 14 AND DATEDIFF(MONTH, wh.DateOfEmploymentTo, GETDATE()) <= 3 ))
OR
((DATEDIFF(DAY, wh.DateOfEmploymentFrom, wh.DateOfEmploymentTo) > 14 AND DATEDIFF(MONTH, wh.DateOfEmploymentTo, GETDATE()) <= 6))
OR
(GETDATE() BETWEEN wh.DateOfEmploymentFrom AND wh.DateOfEmploymentTo)
OR (wh.DateOfEmploymentFrom > GETDATE() OR wh.DateOfEmploymentTo > GETDATE())
GROUP BY tj.JobSeeker_ID))
AND (tblJobSeekerDetails.JobSeeker_ID NOT IN (SELECT DISTINCT te.JobSeeker_ID -- Exclude jobseekers that were recently availed to a project
FROM tblJobSeekerDetails te INNER JOIN tbl_RandomisedJobseeker rj
ON te.JobSeeker_ID = rj.JobseekerID
WHERE (GETDATE() < rj.ExcludedTo)
GROUP BY te.JobSeeker_ID))
END
This stored procedure returns multiple records for jobseekers that have more than one "OtherSkills". I need to modify it so that it only returns one. I presume this is due to the join. Yet, I cant just return the first "OtherSkill". I need all the skills for a given jobseeker so that I can compare it with the criteria that is received.
(I just started considering the possibility to make use of a table variable. Sometimes writing out a question really helps :))
I solved this by making use of the WITH clause to load all the data from the jobseeker table that I need to filter on to do my counting. I also do the filtering for the skills in this WITH:
ALTER PROCEDURE [dbo].[stp_RandomisationResultCount]
#noOfRows INT,
#subcouncil INT,
#wards VARCHAR(MAX) = NULL,
#suburbs VARCHAR(MAX) = NULL,
#courts VARCHAR(MAX) = NULL,
#skills VARCHAR(MAX) = NULL,
#isDisabled VARCHAR(1) = NULL,
#hasQualification VARCHAR(1) = NULL,
#gender VARCHAR(1) = NULL,
#age INT = NULL
AS
BEGIN
WITH JobSeekerDetails AS
(
SELECT DISTINCT jsd.JobSeeker_ID,
jsd.SubCouncilID,
jsd.WardID,
jsd.Suburb,
jsd.RoadType,
jsd.Disability,
jsd.HasTertiaryQualification,
jsd.Gender,
jsd.IdentityNumber,
jsd.TypeID,
jsd.IsExcludedFromRandomisation
FROM dbo.tblJobSeekerDetails jsd
LEFT JOIN tbl_lnk_JobSeeker_OtherSkills jos
ON jsd.JobSeeker_ID = jsd.JobSeeker_ID
LEFT JOIN tblOtherSkills os
ON jos.OtherSkillsID = os.OtherSkillsID
WHERE ((os.OtherSkillsID in (SELECT s.Item FROM ufn_SplitIntArray(#skills, ',') s)) OR (#skills IS NULL))
)
SELECT COUNT(jsd.JobSeeker_ID) resultCount
FROM tblJobSeekerDetails jsd
INNER JOIN JobSeekerDetails
ON jsd.JobSeeker_ID = JobSeekerDetails.JobSeeker_ID
WHERE (jsd.SubCouncilID = #subcouncil)
AND ((jsd.WardID IN (SELECT s.Item FROM ufn_SplitIntArray(#wards, ',') s)) OR (#wards IS NULL))
AND ((jsd.Suburb IN (SELECT s.Item FROM ufn_SplitIntArray(#suburbs, ',') s)) OR (#suburbs IS NULL))
AND ((jsd.RoadType IN (SELECT s.Item FROM ufn_SplitIntArray(#courts, ',') s)) OR (#courts IS NULL))
AND ((jsd.Disability = #isDisabled) OR (#isDisabled IS NULL))
AND ((jsd.HasTertiaryQualification = #hasQualification) OR (#hasQualification IS NULL))
AND ((jsd.Gender = #gender) OR (#gender IS NULL))
AND ((ISNUMERIC(jsd.IdentityNumber) = 1 AND
jsd.IdentityNumber NOT LIKE '%.%' AND
DATEPART(YEAR, GETDATE()) - (CONVERT(INT, '19' + SUBSTRING(jsd.IdentityNumber, 1, 2), 100)) = #age) OR (#age IS NULL))
AND (jsd.TypeID = 1)--Jobseekers only
AND (jsd.IsExcludedFromRandomisation <> 1 OR jsd.IsExcludedFromRandomisation IS NULL)--Explicitly excluded jobseekers
AND (jsd.JobSeeker_ID not in (SELECT DISTINCT tj.JobSeeker_ID --Exclude Jobseekers as per stipulated exclusion period
FROM tblJobSeekerDetails tj
INNER JOIN tblJobSeekerEmploymentHistory wh
ON tj.JobSeeker_ID = wh.JobSeekerID
WHERE ((DATEDIFF(DAY, wh.DateOfEmploymentFrom, wh.DateOfEmploymentTo) <= 14 AND DATEDIFF(MONTH, wh.DateOfEmploymentTo, GETDATE()) <= 3 ))
OR
((DATEDIFF(DAY, wh.DateOfEmploymentFrom, wh.DateOfEmploymentTo) > 14 AND DATEDIFF(MONTH, wh.DateOfEmploymentTo, GETDATE()) <= 6))
OR
(GETDATE() BETWEEN wh.DateOfEmploymentFrom AND wh.DateOfEmploymentTo)
OR (wh.DateOfEmploymentFrom > GETDATE() OR wh.DateOfEmploymentTo > GETDATE())
GROUP BY tj.JobSeeker_ID))
AND (jsd.JobSeeker_ID NOT IN (SELECT DISTINCT te.JobSeeker_ID -- Exclude jobseekers that were recently availed to a project
FROM tblJobSeekerDetails te INNER JOIN tbl_RandomisedJobseeker rj
ON te.JobSeeker_ID = rj.JobseekerID
WHERE (GETDATE() < rj.ExcludedTo)
GROUP BY te.JobSeeker_ID))
END