SQL Server select where most columns match - sql

I have a stored procedure that can have 1 to 4 variables passed to it and it must return the rows where the most columns match or if there are no matching records it returns the default ones (which are null).
The sequence needs to be distinct.
Example table with data:
Client_Id Project_ID Phase Task Employee Sequence
--------- ---------- ----- ---- -------- --------
NULL NULL NULL NULL Chris 1
NULL NULL NULL NULL Bob 100
500 NULL NULL NULL Joe 1
500 2 NULL NULL Max 1
So the results for Client 100, any project, phase or task would simply be the default NULL records of Chris and Bob. For Client 500 the results would be Joe and Bob. For Client 500, Project 2 the result would be Max and Bob.
Right now I am doing this query by checking the task first then joining it with a query by phase and checking that no rows overlap and doing the same for project then client. It seems incredibly inefficient and there has to be a smarter way about this. Any thoughts?
EDIT - Some query examples, I check first for the case where everything matches
insert into #TempTracking
select p.employee, p.sequence
from invoices i, projects p
where i.client_id = p.client_id
and i.project_no = p.project_no
and i.phase = p.phase
and i.task = p.task
Then I make the queries less and less specific and check that the sequence does not already exist.
insert into #TempTracking
select p.employee, p.sequence
from invoices i, projects p
where (i.client_id = p.client_id or i.client_id is null)
and (i.project_no = p.project_no or i.project_no is null)
and (i.phase = p.phase or i.phase is null)
and (i.task = p.task or i.task is null)
and NOT EXISTS ( SELECT * FROM #TempTracking t WHERE t.sequence = p.sequence )

"Most of the columns match" is very vague, but I assume you mean that if they search for null, or if the value in the table is null then assume this record could be included.
If you want the most matching row or all rows that match nothing, then you will need to do something like this (it's starting to get very long)
DECLARE #Client_Id VARCHAR(MAX) = '500'
DECLARE #Project_ID VARCHAR(MAX) = '2'
DECLARE #Phase VARCHAR(MAX) = NULL
DECLARE #Task VARCHAR(MAX) = NULL
SELECT Employee, Sequence
FROM
(SELECT Employee, Sequence,
(
CASE WHEN (Client_Id = #Client_Id OR Client_Id IS NULL OR #Client_Id IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Project_ID = #Project_ID OR Project_ID IS NULL OR #Project_ID IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Phase = #Phase OR Phase IS NULL OR #Phase IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Task = #Task OR Task IS NULL OR #Task IS NULL) THEN 1 ELSE 0 END
) AS MatchCount
WHERE MatchCount =
(
SELECT MAX(
CASE WHEN (Client_Id = #Client_Id OR Client_Id IS NULL OR #Client_Id IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Project_ID = #Project_ID OR Project_ID IS NULL OR #Project_ID IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Phase = #Phase OR Phase IS NULL OR #Phase IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Task = #Task OR Task IS NULL OR #Task IS NULL) THEN 1 ELSE 0 END
)
FROM myTable
)
-- Now prevent for duplicate sequence numbers
AND NOT EXISTS (
SELECT Employee, Sequence
FROM
(SELECT Employee, Sequence,
(
CASE WHEN (Client_Id = #Client_Id OR Client_Id IS NULL OR #Client_Id IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Project_ID = #Project_ID OR Project_ID IS NULL OR #Project_ID IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Phase = #Phase OR Phase IS NULL OR #Phase IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Task = #Task OR Task IS NULL OR #Task IS NULL) THEN 1 ELSE 0 END
) AS MatchCount
FROM myTable) mt2
WHERE mt2.MatchCount =
(
SELECT MAX(
CASE WHEN (Client_Id = #Client_Id OR Client_Id IS NULL OR #Client_Id IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Project_ID = #Project_ID OR Project_ID IS NULL OR #Project_ID IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Phase = #Phase OR Phase IS NULL OR #Phase IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Task = #Task OR Task IS NULL OR #Task IS NULL) THEN 1 ELSE 0 END
)
FROM myTable
)
AND mt2.Sequence = myTable.Sequence AND mt2.MatchCount > myTable.MatchCount
)
Note: This will return all records in the table when the number of matching fields is zero.
I'm sure they're are ways this could be cleaned up to not be so verbose by inserting all matching rows into a temp table and including the number of columns that match (MatchCount), there by reducing the query considerably.
Now, since you want unique Sequences and the highest matching row / rows to be returned the result you're looking for is more like this:
DECLARE #Client_Id VARCHAR(MAX) = '500'
DECLARE #Project_ID VARCHAR(MAX) = '3'
DECLARE #Phase VARCHAR(MAX) = NULL
DECLARE #Task VARCHAR(MAX) = NULL
INSERT INTO #myTempTable SELECT Employee, Sequence,
(
CASE WHEN (Client_Id = #Client_Id OR Client_Id IS NULL OR #Client_Id IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Project_ID = #Project_ID OR Project_ID IS NULL OR #Project_ID IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Phase = #Phase OR Phase IS NULL OR #Phase IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Task = #Task OR Task IS NULL OR #Task IS NULL) THEN 1 ELSE 0 END
) AS MatchCount,
(
CASE WHEN (Client_Id IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Project_ID IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Phase IS NULL) THEN 1 ELSE 0 END +
CASE WHEN (Task IS NULL) THEN 1 ELSE 0 END
) AS NullCount
-- ,(
-- CASE WHEN (Client_Id = #Client_Id OR #Client_Id IS NULL) THEN 1 ELSE 0 END +
-- CASE WHEN (Project_ID = #Project_ID OR #Project_ID IS NULL) THEN 1 ELSE 0 END +
-- CASE WHEN (Phase = #Phase OR #Phase IS NULL) THEN 1 ELSE 0 END +
-- CASE WHEN (Task = #Task OR #Task IS NULL) THEN 1 ELSE 0 END
-- ) AS MatchCountWithoutNulls
SELECT Employee, Sequence
FROM #myTempTable mtt
WHERE MatchCount = (
SELECT MAX(MatchCount)
FROM #myTempTable mtt2
WHERE mtt2.Sequence = mtt.Sequence
)
AND NullCount = (
SELECT MIN(NullCount)
FROM #myTempTable mtt2
WHERE mtt2.Sequence = mtt.Sequence
)
Or something very close to that, I don't have a test table made up atm so I can't kick it around and see.

Related

SQL CASE switch for parameter

I have a parameter that can be 1 of 3 possible values 0, 2 or NULL (these are values for an enum 0 is Pending, 1 is UnderReview and 2 is Closed). If it is NULL it should retrieve all regardless of the Status but If it is 2 it should retrieve all the closed ones however if the value is 0 it should retrieve the ones that are pending or under review. This last one means that I want to retrieve records that have a status of either 0 or 1. I have the following code so far and tried with a CASE switch but it doesn't work.
SELECT * FROM PurchaseOrder
WHERE (CreationDate >= #StartDate AND CreationDate <= #EndDate)
AND (#POStatus IS NULL OR [Status] = #POStatus)
AND (#POStatus IS NULL OR [Status] = CASE #POStatus WHEN 0 THEN 1 END)
AND (#PurchaseOrderIdSearch IS NULL OR PurchaseOrderId LIKE #PurchaseOrderIdSearch)
AND EmployeeId = #EmployeeId
ORDER BY CreationDate DESC, PurchaseOrderId DESC
I solved it adding an if statement, I was looking for a simpler way to do it to avoid repetition, this is how it looks like now:
IF #POStatus = 0
BEGIN
SELECT * FROM PurchaseOrder
WHERE (CreationDate >= #StartDate AND CreationDate <= #EndDate)
AND (([Status] = #POStatus)
OR ([Status] = 1))
AND (#PurchaseOrderIdSearch IS NULL OR PurchaseOrderId LIKE #PurchaseOrderIdSearch)
AND EmployeeId = #EmployeeId
ORDER BY CreationDate DESC, PurchaseOrderId DESC
END
ELSE
BEGIN
SELECT * FROM PurchaseOrder
WHERE (CreationDate >= #StartDate AND CreationDate <= #EndDate)
AND (#POStatus IS NULL OR [Status] = #POStatus)
AND (#PurchaseOrderIdSearch IS NULL OR PurchaseOrderId LIKE #PurchaseOrderIdSearch)
AND EmployeeId = #EmployeeId
ORDER BY CreationDate DESC, PurchaseOrderId DESC
END
I suppose you're looking for something like
DECLARE #MyParam INT; --Try to set 0, 1 or 2
SELECT *
FROM
(
VALUES
(0),
(1),
(2)
) T(Value)
WHERE (Value = #MyParam) OR (#MyParam IS NULL);
Here is a db<>fiddle to see how it's working.
Update:
It seems like you're looking for
DECLARE #MyParam INT; --Try to set 0, 1 or 2
SELECT *
FROM
(
VALUES
(0),
(1),
(2)
) T(Value)
WHERE
(
CASE WHEN #MyParam = 0 OR #MyParam = 1 THEN 1 ELSE 0 END = 1
AND Value IN(0, 1)
)
OR
(Value = #MyParam AND #MyParam = 2)
OR
#MyParam IS NULL;
Here is a db<>fiddle

Best performance for paging query when using multiple statements in sql?

It is a bit complicated query but let me elaborate,
i have got multiple filter parameters in my procedure,
also a view named Vw1 and its regarded my main object in query that most of the filter parameters are filtered against this view that is located in another server,then i need to compare this view to another table and check two sides columns for possible conflict and then check if there is any conflict.
you can see my query below
ALTER PROC [dbo].[spGetAyandehVagozariWithConflict]
#Take INT,
#Skip INT,
#FromVagozariDate NVARCHAR(10),
#ToVagozariDate NVARCHAR(10),
#OrderBankCode NVARCHAR(4)=null,
#OrderBrCode NVARCHAR(7)=null,
#BenefBrCode NVARCHAR(4)=null,
#FromAmount NVARCHAR(50)=null,
#ToAmount NVARCHAR(50)=null,
#CheqSerie NVARCHAR(50)=null,
#CheqSerial NVARCHAR(10)=null,
#CheqStatus NVARCHAR(4)=null,
#CreditorNationalCode VARCHAR(20)=NULL,
#CheqType NVARCHAR(4)=null,
#BenefAccn NVARCHAR(13)=null,
#FromMatDate NVARCHAR(10)=null,
#ToMatDate NVARCHAR(10)=null,
#FromTaeenVaziatDate NVARCHAR(10)=null,
#ToTaeenVaziatDate NVARCHAR(10)=NULL,
#HasConflict VARCHAR(4)=null,
#TotalCnt INT OUTPUT,
#SUM BIGINT OUTPUT
AS
BEGIN
DECLARE #Query NVARCHAR(MAX)=''
IF(NULLIF(#FromVagozariDate,'') IS null)
SET #FromVagozariDate='NULL'
IF(NULLIF(#ToVagozariDate,'') IS null)
SET #ToVagozariDate='NULL'
IF(NULLIF(#OrderBrCode,'') IS null)
SET #OrderBrCode='NULL'
IF(NULLIF(#OrderBankCode,'') IS null)
SET #OrderBankCode='NULL'
IF(NULLIF(#BenefBrCode,'') IS null)
SET #BenefBrCode='NULL'
IF(NULLIF(#FromAmount,'') IS null)
SET #FromAmount='NULL'
IF(NULLIF(#ToAmount,'') IS null)
SET #ToAmount='NULL'
IF(NULLIF(#CheqSerie,'') IS null)
SET #CheqSerie='NULL'
IF(NULLIF(#CheqSerial,'') IS null)
SET #CheqSerial='NULL'
IF(NULLIF(#CheqStatus,'') IS null)
SET #CheqStatus='NULL'
IF(NULLIF(#CheqType,'') IS null)
SET #CheqType='NULL'
IF(NULLIF(#BenefAccn,'') IS null)
SET #BenefAccn='NULL'
IF(NULLIF(#ToMatDate,'') IS null)
SET #ToMatDate='NULL'
IF(NULLIF(#FromMatDate,'') IS null)
SET #FromMatDate='NULL'
IF(NULLIF(#FromTaeenVaziatDate,'') IS null)
SET #FromTaeenVaziatDate='NULL'
IF(NULLIF(#ToTaeenVaziatDate,'') IS null)
SET #ToTaeenVaziatDate='NULL'
IF(NULLIF(#HasConflict,'') IS null)
SET #HasConflict='NULL'
IF(NULLIF(#CreditorNationalCode,'') IS null)
SET #CreditorNationalCode='NULL'
IF #FromVagozariDate<>'NULL'
BEGIN
SET #FromVagozariDate=REPLACE(#FromVagozariDate,'/','')
END
IF #ToVagozariDate<>'NULL'
BEGIN
SET #ToVagozariDate=REPLACE(#ToVagozariDate,'/','')
END
IF #FromMatDate<>'NULL'
BEGIN
SET #FromMatDate=REPLACE(#FromMatDate,'/','')
END
IF #ToMatDate<>'NULL'
BEGIN
SET #ToMatDate=REPLACE(#ToMatDate,'/','')
END
IF #FromTaeenVaziatDate<>'NULL'
BEGIN
SET #FromTaeenVaziatDate=REPLACE(#FromTaeenVaziatDate,'/','')
SET #FromTaeenVaziatDate=SUBSTRING(#FromTaeenVaziatDate,3,6)
END
IF #ToTaeenVaziatDate<>'NULL'
BEGIN
SET #ToTaeenVaziatDate=REPLACE(#ToTaeenVaziatDate,'/','')
SET #ToTaeenVaziatDate=SUBSTRING(#ToTaeenVaziatDate,3,6)
END
IF #OrderBankCode<>'NULL'
BEGIN
--SET #OrderBankCode='0'+#OrderBankCode;
SET #OrderBankCode=dbo.LeftPad(#OrderBankCode,'0',3)
END
IF(#BenefBrCode<>'NULL')
BEGIN
SET #BenefBrCode=dbo.LeftPad(#BenefBrCode,'0',4)
END
IF(#OrderBrCode<>'NULL')
BEGIN
SET #OrderBrCode=dbo.LeftPad(#OrderBrCode,'0',4)
END
SET #Query=#Query+N'
SELECT *
INTO #Vw1
FROM [LinkedServer].DbName.dbo.Vw1 vd
where (vd.mat_date BETWEEN '+''''+#FromMatDate+''''+' AND'+''''+ #ToMatDate+''''+' OR ('+''''+#FromMatDate+''''+' =''NULL'' AND '+''''+#ToMatDate+''''+' =''NULL'' )) AND
(dbo.LeftPad(vd.order_bank_code,''0'',3)= '+''''+#OrderBankCode+''''+' OR '+''''+#OrderBankCode+''''+' =''NULL'') AND
(dbo.LeftPad(vd.order_brcode,''0'',4)= '+''''+#OrderBrCode+''''+' OR '+''''+#OrderBrCode+''''+' =''NULL'') AND
(dbo.LeftPad(vd.Benef_br_code,''0'',4)= '+''''+#BenefBrCode+''''+' OR '+''''+#BenefBrCode+''''+' =''NULL'') AND
(substring(vd.amount, patindex(''%[^0]%'',vd.amount), 10) BETWEEN '+''''+#FromAmount+''''+' AND '+''''+#ToAmount+''''+' OR ('+''''+#FromAmount+''''+' =''NULL'' AND '+''''+#ToAmount+''''+' =''NULL'')) AND
(RTRIM(LTRIM(vd.chq_serie))= '+''''+#CheqSerie+''''+' OR '+''''+#CheqSerie+''''+' =''NULL'') AND
(RTRIM(LTRIM(vd.chq_serial))= '+''''+#CheqSerial+''''+' OR '+''''+#CheqSerial+''''+' =''NULL'') AND
(vd.Chq_stat= '+''''+#CheqStatus+''''+' OR '+''''+#CheqStatus+''''+' in (''NULL'',''-1'')) AND
(vd.chq_type= '+''''+#CheqType+''''+' OR '+''''+#CheqType+''''+' =''NULL'') AND
(vd.benef_acno= '+''''+#BenefAccn+''''+' OR '+''''+#BenefAccn+''''+' =''NULL'') AND
((vd.taeen_vaziat_date is null AND ('+''''+#CheqStatus+''''+'=''-1'')) or('+''''+#CheqStatus+''''+'<>''-1'') ) AND
(vd.vagozari_date BETWEEN '+''''+#FromVagozariDate+''''+' AND '+''''+#ToVagozariDate+''''+' OR ('+''''+#FromVagozariDate+''''+' =''NULL'' AND '+''''+#ToVagozariDate+''''+' =''NULL'')) AND
(vd.taeen_vaziat_date BETWEEN '+''''+#FromTaeenVaziatDate+''''+' AND '+''''+#ToTaeenVaziatDate+''''+' OR ('+''''+#ToTaeenVaziatDate+''''+' =''NULL'' AND '+''''+#FromTaeenVaziatDate+''''+' =''NULL''))
order by system_no
select distinct cast(benef_acno as bigint) benef_acno
into #acno
from #Vw1
select ACNO,CUSTNO
into #ACTINFO
from [LinkServer1].[Db1].[dbo].[ACTINFO] af
where accno_id in (select * from #acno)
select [ECONOMIC-CODE],CUSTNO,FIRSTNAME +'' ''+LASTNAME CUSTNAME
into #CUSTINFO
from [LinkServer1].[Db1].[dbo].[CUSTINFO]
where CustNo_Id in (select cast(CUSTNO as bigint) from #ACTINFO)
SELECT
vd.*,
ct.Title CheqTypeTitle,
af.CUSTNO,cf.CUSTNAME,
--'''' as CUSTNO,'''' CUSTNAME,
cs.Status CheqStatusTitle,
av.Id AyandehVagozariId,
p.ParticipantName BenefBankName,
CASE WHEN ISNULL(vd.vagozari_date,'''') <> COALESCE(REPLACE(av.VagozariDate,''/'',''''),vd.vagozari_date,'''') THEN 1 ELSE 0 END VagozariDateHasConflict,
CASE WHEN ISNULL(dbo.LeftPad(vd.order_bank_code,''0'',3),'''') <> COALESCE(av.Order_Bank_Code,dbo.LeftPad(vd.order_bank_code,''0'',3),'''') THEN 1 ELSE 0 END OrderBankCodeHasConflict,
CASE WHEN ISNULL(dbo.LeftPad(vd.order_brcode,''0'',4),'''') <> COALESCE(av.Order_brCode,dbo.LeftPad(vd.order_brcode,''0'',4),'''') THEN 1 ELSE 0 END OrderBrCodeHasConflict,
CASE WHEN ISNULL(dbo.LeftPad(vd.Benef_br_code,''0'',4),'''') <> COALESCE(av.Benef_Br_Code,dbo.LeftPad(vd.Benef_br_code,''0'',4),'''') THEN 1 ELSE 0 END BenefBrCodeHasConflict,
CASE WHEN ISNULL(substring(vd.amount, patindex(''%[^0]%'',vd.amount), 10),'''') <> COALESCE(av.Amount,substring(vd.amount, patindex(''%[^0]%'',vd.amount), 10),'''') THEN 1 ELSE 0 END AmountHasConflict,
CASE WHEN ISNULL(vd.chq_serie,'''') <> COALESCE(av.Chq_serie,vd.chq_serie,'''') THEN 1 ELSE 0 END CheqSerieHasConflict,
CASE WHEN ISNULL(RTRIM(LTRIM(vd.chq_serial)),'''') <> COALESCE(av.Chq_Serial,RTRIM(LTRIM(vd.chq_serial)),'''') THEN 1 ELSE 0 END CheqSerialHasConflict,
CASE WHEN ISNULL(vd.chq_type,'''') <> COALESCE(av.Chq_Type,vd.chq_type,'''') THEN 1 ELSE 0 END CheqTypeHasConflict,
CASE WHEN ISNULL(vd.benef_acno,'''') <> COALESCE(av.Benef_Acno,vd.benef_acno,'''') THEN 1 ELSE 0 END BenefAcnoHasConflict,
CASE WHEN ISNULL(vd.mat_date,'''') <> COALESCE(REPLACE(av.Mat_Date,''/'',''''),vd.mat_date,'''') THEN 1 ELSE 0 END MatDateHasConflict,
CASE WHEN ISNULL(cf.CUSTNO,'''') <> COALESCE(av.CUSTNO,cf.CUSTNO COLLATE DATABASE_DEFAULT,'''') THEN 1 ELSE 0 END CustNoHasConflict,
--CASE WHEN ISNULL(vd.taeen_vaziat_date,'''') <> COALESCE(av.Taeen_Vaziat_Date,vd.taeen_vaziat_date,'''') THEN 1 ELSE 0 END TaeenVaziatDateHasConflict,
0 as TaeenVaziatDateHasConflict,
CASE WHEN ISNULL(vd.Chq_stat,'''') <> COALESCE(av.Chq_Status,vd.Chq_stat,'''') THEN 1 ELSE 0 END CheqStatusHasConflict
--0 as VagozariDateHasConflict,
--0 as OrderBankCodeHasConflict,
--0 as OrderBrCodeHasConflict,
--0 as BenefBrCodeHasConflict,
--0 as AmountHasConflict,
--0 as CheqSerieHasConflict,
--0 as CheqSerialHasConflict,
--0 as CheqTypeHasConflict,
--0 as BenefAcnoHasConflict,
--0 as MatDateHasConflict,
--0 as TaeenVaziatDateHasConflict
INTO #temp
FROM #vw_faranam_vagozari_chakavak vd
LEFT JOIN #ACTINFO af on vd.benef_acno=af.ACNO COLLATE Arabic_CI_AS
LEFT JOIN #CUSTINFO cf on af.CUSTNO=cf.CUSTNO COLLATE Arabic_CI_AS
LEFT JOIN [AyandehVagozari] av ON av.SystemNo=vd.system_no
LEFT JOIN [Cheque_Type_Biha] ct ON ct.Code=vd.chq_type
LEFT JOIN [ChequeStatusForBiha] cs ON cs.Id=vd.Chq_stat
LEFT JOIN [Participant] p ON ''0''+p.ParticipantCode=vd.order_bank_code
WHERE (cf.[ECONOMIC-CODE]= '+''''+#CreditorNationalCode+''''+' OR '+''''+#CreditorNationalCode+''''+' =''NULL'')
order by vd.system_no
DELETE t FROM(
SELECT *,ROW_NUMBER() OVER(partition by system_no order by AyandehVagozariId desc) rn FROM
#temp
)t
where rn>1
SELECT *,
case when (VagozariDateHasConflict=1 or OrderBankCodeHasConflict=1 or OrderBrCodeHasConflict =1 OR BenefBrCodeHasConflict=1
or AmountHasConflict=1 or CheqSerieHasConflict=1 or CheqSerialHasConflict=1 or CustNoHasConflict=1
or CheqStatusHasConflict=1 or CheqTypeHasConflict=1 or BenefAcnoHasConflict=1 or MatDateHasConflict=1 or TaeenVaziatDateHasConflict=1)
then 1 else 0 end HasConflict
INTO #TmpResult
FROM #temp
order by system_no
--here is where i filter my last parameter but it seems too late..because alot of records already involved !
SELECT *,ROW_NUMBER() over (ORDER BY system_no) RowNumber
into #finalTemp
FROM
#TmpResult
where (HasConflict=1 and '+''''+#HasConflict+''''+'=''1'')
OR (HasConflict=0 and '+''''+#HasConflict+''''+'=''0'')
OR ('+''''+#HasConflict+''''+'=''NULL'')
order by system_no
SELECT #Total=##ROWCOUNT
select #Sum=isnull(SUM(cast(amount as bigint)),0) from
#finalTemp
select * from
#finalTemp
WHERE RowNumber >'+CAST(#Skip AS NVARCHAR(10))+' AND RowNumber<=('+CAST(#Skip+#Take AS NVARCHAR(10))+')
'
PRINT #Query
EXEC sp_executesql #Query,N'#Total int output,#Sum bigint output',#TotalCnt OUTPUT,#SUM OUTPUT
END
due to performance issues i had to write it in dynamic way,But the problem is that i could not wrap my head around paging in this query, bacause as you see i should put paging line in the end of query because #HasConflict parameters exist and i cannot check it earlier,and in this way my paging seems pointless because i'm dealing with huge load of data ...
also i cannot use offset for paging because my sql version is too old ...

"Error" value on name and description creating strange functionality

I got a raw data file with its content looking like this:
MSN_Check,Text,25,MSN check
0,Text,1,(Result)
HWIMPL,Text,10,HWIMPL version reading
007F,Text,6,(Measure)
1,Text,1,(Result)
VHW,Text,10,FMT hardware version
494131383346,Text,10,(Measure)
0,Text,1,(Result)
TOTAL_VER,Text,25,Total version reading
313031303130,Text,6,(Measure)
1,Text,1,(Result)
CAL_MCU,Text,25,Total version reading
05,Text,6,(Measure)
Error,Text,25,Error
9.8499985089315E-07,Numeric,Float 3.3,(Measure)
CAL_EEPROM,Text,25,Total version reading
05,Numeric,Float 3.3,(Measure)
1,Text,1,(Result)
And I needed to extract and store in variables the name, example MSN_Check ,the description, example MSN check its result for example 0 and its measure , for example 007F but in some places I have results only or measures only so just spliting them wouldn't have helped.So my idea was:
First of all I created a template table named dbo.template that looks like this:
Name TestDescription Measure Result ID
----------------------------------------------
MSN_Check MSN check 0 1 1
HWIMPL HWIMPL version reading 1 1 2
VHW FMT hardware version 1 1 3
TOTAL_VER Total version reading 1 1 4
CAL_MCU Total version reading 1 0 5
Error Error 1 0 6
CAL_EEPROM Total version reading 1 1 7
In this table we have the name,description,if_measure(meaning 1 if we have a measure or 0 if we dont) and the if_result.And I made a query looking like this:
DECLARE #crlf AS CHAR(2) = CHAR(13) + CHAR(10)
declare #testname varchar(max),#testDescription varchar(max), #if_measure char(1), #if_result char(1), #row int = '1', #id int
set #LogEntry = (SELECT REPLACE(#LogEntry,#crlf,','))
declare #name varchar(max),#description varchar(MAX), #measure varchar(20), #result char(1)
declare #Output table(OutTestName varchar(max),OUTTestDescription varchar(max), OutMeasure varchar(50), OutResult varchar(50))
declare #maximum int = (select MAX(ID) from dbo.template_FMT)
declare #LogEntry1 as nvarchar(max)
declare #LogEntry2 as nvarchar(max)
while #row <= #maximum
BEGIN
set #name = null
set #description = null
set #measure = null
set #result = null
set #testname = (select Name from dbo.template_FMT where ID = #row)
set #testDescription = (select TestDescription from dbo.template_FMT where ID = #row)
set #if_measure = (select Measure from dbo.template_FMT where ID = #row)
set #if_result = (select Result from dbo.template_FMT where ID = #row)
set #id = (select ID from dbo.Split(#LogEntry, ',') where Data = #testname)
SELECT #LogEntry1 = Name FROM dbo.template_FMT where id = #row
set #name = #LogEntry1
SELECT #LogEntry2 = TestDescription FROM dbo.template_FMT where id = #row
set #description = #LogEntry2
if #if_measure > 0 and #if_result > 0
begin
set #measure = (select Data from dbo.Split(#LogEntry, ',') where ID = #id+4)
set #result = (select Data from dbo.Split(#LogEntry, ',') where ID = #id+8)
insert into #Output (OutTestName, OUTTestDescription, OutMeasure, OutResult) Values(#name,#description, #measure, #result)
end
if #if_measure > 0 and #if_result = 0
begin
set #measure = (select Data from dbo.Split(#LogEntry, ',') where ID = #id+4)
set #result = null
insert into #Output (OutTestName, OUTTestDescription, OutMeasure, OutResult) Values(#name,#description, #measure, #result)
end
if #if_measure = 0 and #if_result > 0
begin
set #measure = null
set #result = (select Data from dbo.Split(#LogEntry, ',') where ID = #id+4)
insert into #Output (OutTestName, OUTTestDescription, OutMeasure, OutResult) Values(#name,#description, #measure, #result)
end
set #row = #row + 1
END
select * from #Output
And it worked! but the only problem I have is where I have the row with the name Error with the description Error,it would return the last remembered value so instead of having
CAL_MCU Total version reading 05 NULL
Error Error 9.8499985089315E-07 NULL
CAL_EEPROM Total version reading 05 1
I get:
CAL_MCU Total version reading 05 NULL
Error Error 05 NULL
CAL_EEPROM Total version reading 05 1
And I would like to store the Error cant find Result with ID into variables if any of you have any suggestions :)
P.S. I think it has something to do with the fact that the name and description have the same name (Error)
I believe that your problem can be solved without the need for while loops and string splitting functions. I recommend using the OPENROWSET function to read your raw data file as a standard table. You can then use standard T-SQL query to format the result into the desired output.
The first step is to ensure that ad-hoc queries is enable on your server this can be accomplished by executing the following command.
sp_configure 'show advanced options', 1;
RECONFIGURE;
GO
sp_configure 'Ad Hoc Distributed Queries', 1;
RECONFIGURE;
The next step is to define a format file for your text file. This will help SQL Server understand the text file structure when loading the raw data. Based on the supplied sample data your format file should look as follow:
10.0
4
1 SQLCHAR 0 100 "," 1 Col1 SQL_Latin1_General_CP1_CI_AS
2 SQLCHAR 0 100 "," 2 Col2 SQL_Latin1_General_CP1_CI_AS
3 SQLCHAR 0 100 "," 3 Col3 SQL_Latin1_General_CP1_CI_AS
4 SQLCHAR 0 100 "\r\n" 4 Col4 SQL_Latin1_General_CP1_CI_AS
I have uploaded the format file and example raw data file I have used to test the example at the following links:
http://www.filedropper.com/format
http://www.filedropper.com/rawdatafile
The final step is to run the OPENROWSET query to load the file data and transform the data to the desired output. If you are using SQL Server 2008 r2 then the following query should work:
-- 2008 R2 Version
WITH CTE_VariableRawData
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 0)) AS ID
,[RawData].Col1 AS [VariableOrMeasure]
,(
CASE [RawData].Col4
WHEN '(Result)' THEN 0
WHEN '(Measure)' THEN 0
ELSE 1
END
) AS IsVariable
,(
CASE [RawData].Col4
WHEN '(Result)' THEN 1
ELSE 0
END
) AS IsResult
,(
CASE [RawData].Col4
WHEN '(Measure)' THEN 1
ELSE 0
END
) AS IsMeasure
,[RawData].Col4 AS [Description]
FROM OPENROWSET(BULK N'C:\temp\raw_data_file.txt', FORMATFILE = 'c:\temp\format.txt') AS [RawData]
)
,
CTE_RawDataByVariableID
AS
(
SELECT ID
,(
SELECT SUM([IsVariable])
FROM CTE_VariableRawData RunningTotal
WHERE RunningTotal.ID <= CTE_VariableRawData.ID
) AS VariableID
,[VariableOrMeasure]
,[IsVariable]
,[IsResult]
,[IsMeasure]
,[Description]
FROM CTE_VariableRawData
)
SELECT VariableID
,MAX(
CASE [IsVariable]
WHEN 1 THEN [VariableOrMeasure]
ELSE NULL
END
) AS [Variable]
,MAX(
CASE [IsVariable]
WHEN 1 THEN [Description]
ELSE NULL
END
) AS [Description]
,MAX(
CASE [IsMeasure]
WHEN 1 THEN [VariableOrMeasure]
ELSE NULL
END
) AS [Measure]
,MAX(
CASE [IsResult]
WHEN 1 THEN [VariableOrMeasure]
ELSE NULL
END
) AS [Result]
FROM CTE_RawDataByVariableID
GROUP BY VariableID
ORDER BY VariableID
If you are using SQL Server 2012 or later then the following query will be a bit more optimal:
WITH CTE_VariableRawData
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 0)) AS ID
,[RawData].Col1 AS [VariableOrMeasure]
,(
CASE [RawData].Col4
WHEN '(Result)' THEN 0
WHEN '(Measure)' THEN 0
ELSE 1
END
) AS IsVariable
,(
CASE [RawData].Col4
WHEN '(Result)' THEN 1
ELSE 0
END
) AS IsResult
,(
CASE [RawData].Col4
WHEN '(Measure)' THEN 1
ELSE 0
END
) AS IsMeasure
,[RawData].Col4 AS [Description]
FROM OPENROWSET(BULK N'C:\temp\raw_data_file.txt', FORMATFILE = 'c:\temp\format.txt') AS [RawData]
)
,
CTE_RawDataByVariableID
AS
(
SELECT ID
,SUM([IsVariable]) OVER (ORDER BY ID) AS VariableID
,[VariableOrMeasure]
,[IsVariable]
,[IsResult]
,[IsMeasure]
,[Description]
FROM CTE_VariableRawData
)
SELECT VariableID
,MAX(
CASE [IsVariable]
WHEN 1 THEN [VariableOrMeasure]
ELSE NULL
END
) AS [Variable]
,MAX(
CASE [IsVariable]
WHEN 1 THEN [Description]
ELSE NULL
END
) AS [Description]
,MAX(
CASE [IsMeasure]
WHEN 1 THEN [VariableOrMeasure]
ELSE NULL
END
) AS [Measure]
,MAX(
CASE [IsResult]
WHEN 1 THEN [VariableOrMeasure]
ELSE NULL
END
) AS [Result]
FROM CTE_RawDataByVariableID
GROUP BY VariableID
ORDER BY VariableID;
Note that in both queries you will have to change the location of your raw data file and format file to the desired location within the OPENROWSET(BULK N'C:\temp\raw_data_file.txt', FORMATFILE = 'c:\temp\format.txt') call.

Transact-SQL stored procedure with conditional "AND" logic

I'm working on a stored procedure that is used to filter a grid based on criteria entered by the user. Among the possible criteria they may choose to see transactions that were done between a certain begin and end date. I pass 4 input parameters to the proc - #ClientKey, the client requesting the info, #FilterBy (this is the selected value from a dropdown list in ASP.NET, and essentially tells the proc whether the user is selecting to filter by name, address, date, etc. In this case the #FilterBy value for date is 5), #Value1, which in this instance would be the begin date, and #Value2, which in this instance would be the end date.
In pseudo-code, what I want is:
SELECT ABunchOfColumns
FROM SomeJoinedTables
WHERE SomeCriteria
AND CASE #FilterBy
WHEN 5 THEN d.TransactionTime >= CAST(#Value1 AS Date) AND d.TransactionTime <= CAST(#Value2 AS Date)
Below is the full query. I hope that someone who is more savvy than me with SQL can sort out what I'm trying to do and offer a solution.
Thanks in advance!
#ClientKey int,
#FilterBy int,
#Value1 varchar(150),
#Value2 varchar(150)
AS
BEGIN
SELECT d.pKey AS PaymentKey, d.CaseKey, d.InvoiceID, d.AuthorizationCode, d.TransactionID, d.PaymentType, d.Amount, d.ExpirationDate, d.CardType, d.BankName, d.AccountNumber,
d.AccountType, c.Name, c.Address1, c.City, c.State, c.Zip, cs.PAmount, cs.TranCode, cs.TranDate, cs.[Desc] AS PaymentDescription, cc.[Desc] AS ChargeCodeDescription,
d.TransactionTime, a.Name AS AssociationName, d.PaymentType, c.ClientPaymentID
FROM DebtorPayment d INNER JOIN Cases c
ON d.CaseKey = c.pKey
AND d.ClientKey = c.ClientKey
INNER JOIN CaseSumm cs
ON d.CaseKey = cs.CaseKey
AND d.pKey = cs.Batch
AND d.ClientKey = cs.ClientKey
INNER JOIN ChargeCodes cc
ON c.ClientKey = cc.ClientKey
AND cs.TranCode = cc.RefNum
INNER JOIN AssnCtrl a
ON c.AssnKey = a.pKey
WHERE c.ClientKey = #ClientKey
AND d.AmountAllocated > 0
AND d.TransactionStatus = 'Successful'
AND c.Address1 LIKE CASE
WHEN #FilterBy = 1 THEN '%' + #Value1 + '%'
ELSE c.Address1
END
AND d.Amount = CASE
WHEN #FilterBy = 2 THEN #Value1
ELSE d.Amount
END
AND a.pKey = CASE
WHEN #FilterBy = 3 THEN CAST(#Value1 AS INT)
ELSE a.pKey
END
AND c.ClientPaymentID = CASE
WHEN #FilterBy = 4 THEN #Value1
ELSE c.ClientPaymentID
END
<ProblemArea>
AND CASE #FilterBy
WHEN 5 THEN d.TransactionTime >= CAST(#Value1 AS Date) AND d.TransactionTime <= CAST(#Value2 AS Date)
END
</ProblemArea>
AND c.LName LIKE CASE
WHEN #FilterBy = 6 THEN '%' + #Value1 + '%'
ELSE c.LName
END
ORDER BY d.TransactionTime DESC
END
CASE
WHEN #FilterBy = 5 AND d.TransactionTime >= CAST(#Value1 AS DATE)
AND d.TransactionTime <= CAST(#Value2 AS DATE) THEN 1
ELSE 0
END = 1
Do you mean something like the following?
You might find this link useful too.
Haven't tested the code, just proposing idea - and writing code like this has always felt "wrong" to me - perhaps someone could offer better.
CREATE PROC MyProc
#ClientKey int,
#FilterBy int,
#Value1 varchar(150),
#Value2 varchar(150)
-- NB WITH RECOMPILE, see link (above)
WITH RECOMPILE AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM ...
WHERE
Col1 = CASE
WHEN #FilterBy = 1 THEN #Value1
ELSE Col1
END
AND
1 = CASE
WHEN #FilterBy = 2 AND Col2 > #Value1 AND Col3 < #Value2 THEN 1
WHEN #FilterBy = 2 AND NOT (Col2 > #Value1 AND Col3 < #Value2) THEN 0
ELSE 1
END
END

checking if condition in stored procedure( sql server 2005)

i have an SP where i need to check for if condition
ALTER PROCEDURE [dbo].[spCheck]
#strEmpname VARCHAR(50),
#intReturn INT OUTPUT,
#intWorkdID INT,
#intEmpID INT
AS
BEGIN
IF(#intWorkdID is not null and #intWorkdID != '')
BEGIN
IF EXISTS ( SELECT *
FROM Employee
WHERE [Empname] = #strEmpname
AND WorkID = #intWorkdID
)
SELECT #intReturn = '1'
END
ELSE
IF(#intEmpID is not null and #intEmpID != '')
BEGIN
IF EXISTS ( SELECT *
FROM Employee
WHERE [Empname] = #strEmpname
AND PeopleID = #intEmpID
)
SELECT #intReturn = '1'
END
ELSE IF(#intEmpID is not null and #intEmpID != '')
and(#intWorkdID is not null and #intWorkdID != '')
BEGIN
SELECT #intReturn = '0'
END
END
here based on WorkID,EmpID
1 condition and 2 condition should execute
if both condition fail i need to excute the third condition
can any one tell the syntax for it
thanks
prince
Best way is that you can use
Try something as below:
SELECT #intReturn =
CASE
WHEN #intWorkdID IS NULL THEN 1
WHEN #intWorkdID<>'' THEN 1
WHEN #intEmpID IS NULL THEN 1
WHEN #intEmpID <>'' THEN 1
ELSE 0
END
Case... When
for this
An int can't equal ''.
I'm not sure what you're asking for in your logic, but when an if doesn't match then it runs the else part. You can then have anpther if -> else after that as per your script.