I am trying to return a default value if no such record exists for the given parameters. Here's the sql query:
DECLARE #List VARCHAR(max)
DECLARE #date VARCHAR(max)
SET #List = '''4401366'',''3115880'''
SET #date = '''2018-02-09 00:00:00.000'''
DECLARE #SQL NVARCHAR(max)
SET #SQL = N'
select EmpNo, attendanceStatus =
CASE
WHEN AttDate is null then ''false''
WHEN max(AttTimeIn) is null and max(AttTimeOut) is null THEN ''false''
WHEN max(AttTimeIn) is not null and max(AttTimeOut) is not null then(case when (max(AttTimeIn) < max(AttTimeOut)) then ''false'' else ''true'' end)
WHEN max(AttTimeIn) is not null and max(AttTimeOut) is null THEN ''true''
else ''false''
end
from tablename
where empNo in (' +#list+ ') AND AttDate = ('+ #date +')
group by EmpNo, AttDate'
EXEC sp_executesql #SQL
To be more specific, i want attendanceStatus to return false in case no such record exists for the given date (for each employee). How can I achieve this?
I believe you need something like this, but without data it is difficult to test:
SET #SQL = N'
SELECT T0.EmpNo
, attendanceStatus = CASE
WHEN T1.empNo is null
THEN ''false''
WHEN max(T1.AttTimeIn) is null and max(T1.AttTimeOut) is null
THEN ''false''
WHEN max(T1.AttTimeIn) is not null and max(T1.AttTimeOut) is not null
THEN(CASE WHEN (max(T1.AttTimeIn) < max(T1.AttTimeOut))
THEN ''false'' else ''true'' END)
WHEN max(T1.AttTimeIn) is not null and max(T1.AttTimeOut) is null
THEN ''true''
ELSE ''false''
END
FROM tablename T0
LEFT JOIN tablename T1
ON T1.empNo = T0.empNo
AND T1.AttDate = ('+ #date +')
WHERE T0.empNo in (' +#list+ ')
GROUP BY T0.EmpNo
, T1.AttDate
'
you can try this.
DECLARE #List VARCHAR(max)
DECLARE #date VARCHAR(max)
SET #List = '''4401366'',''3115880'''
SET #date = '''2018-02-09 00:00:00.000'''
DECLARE #SQL NVARCHAR(max)
SET #SQL = N'
select EmpNo, attendanceStatus =
CASE WHEN AttDate = ('+ #date +') THEN
CASE
WHEN max(AttTimeIn) is null and max(AttTimeOut) is null THEN ''false''
WHEN max(AttTimeIn) is not null and max(AttTimeOut) is not null then(case when (max(AttTimeIn) < max(AttTimeOut)) then ''false'' else ''true'' end)
WHEN max(AttTimeIn) is not null and max(AttTimeOut) is null THEN ''true''
ELSE ''false''
END
ELSE ''false'' END
from tablename
where empNo in (' +#list+ ')
group by EmpNo, AttDate'
EXEC sp_executesql #SQL
this should work
DECLARE #List VARCHAR(max)
DECLARE #date VARCHAR(max)
SET #List = '''4401366'',''3115880'''
SET #date = '''2018-02-09 00:00:00.000'''
DECLARE #SQL NVARCHAR(max)
SET #SQL = N'
--check if employee exists
with empTable as (
SELECT DISTINCT EmpNo
FROM tablename
WHERE empNo in (' +#list+ '))
select Et.EmpNo, attendanceStatus =
CASE
WHEN T.AttDate is null then ''false''
WHEN max(T.AttTimeIn) is null and max(T.AttTimeOut) is null THEN ''false''
WHEN max(T.AttTimeIn) is not null and max(T.AttTimeOut) is not null then(case when (max(T.AttTimeIn) < max(T.AttTimeOut)) then ''false'' else ''true'' end)
WHEN max(T.AttTimeIn) is not null and max(T.AttTimeOut) is null THEN ''true''
else ''false''
end
from
empTable eT
LEFT JOIN tablename T ON
et.EmpNo=T.EmpNo
where T.AttDate = ('+ #date +')
group by et.EmpNo, T.AttDate'
EXEC sp_executesql #SQL
I have rewritten your code, simplified your case statement and removed some code
AttDate is null then 'false'
AttDate will never be null because it is included in the where clause
I also changed the data type for #date and made it into a parameterized query for date. Your script is still prone to sql injection because of #List. This can be avoided by splitting it into a table.
I am not sure what you want to replace with a default value. But here is the improved script:
DECLARE #List VARCHAR(max)
DECLARE #date DATE
SET #List = '''4401366'',''3115880'''
SET #date = '2018-02-09'
DECLARE #SQL NVARCHAR(max)
SET #SQL = N'
SELECT coalesce(EmpNo, ''default'') EmpNo,
CASE WHEN i is not null and (i >= o or o is null) THEN ''true'' ELSE ''false'' END
FROM
(
SELECT
Empno,
max(AttTimeIn) over (partition by EmpNo) i,
max(AttTimeOut) over (partition by EmpNo)o
FROM tablename
WHERE empNo in (' +#list+ ') AND AttDate = #date
GROUP BY EmpNo, AttDate
) x
GROUP BY EmpNo'
EXEC sp_executesql #SQL, N'#date date', #date
For example: 'Swati Prakash Phapale' then possible condition are 'prakash swati phapale' , 'swati phapale prakash',prakash swati phapale' or multiple permutation
DECLARE #fName varchar(max) =ltrim(rtrim(isnull('swati','')))
DECLARE #mName varchar(max) =ltrim(rtrim(isnull(' phapale','')))
DECLARE #lName varchar(max) =ltrim(rtrim(isnull(' prakash','')))
DECLARE #FullName varchar(max), #Split char(1)=' ' ,#X1 xml,#i int=0
if len(#mName)!=0
set #FullName = #fName +' ' + #mName +' '+#lName
else
begin
set #FullName = #fName +' '+#lName
end
IF len(#FullName)=0 BEGIN
SET #FullName = 'null' END DECLARE #hit AS varchar(MAX)='',
#EmptyGuid UniqueIdentifier='00000000-0000-0000-0000-000000000000'
SELECT #X1 = CONVERT(xml,' <root> <s>' + REPLACE(#FullName,#Split,'</s> <s>') + '</s> </root> ')
declare #tmp1 as table(name varchar(max))
declare #tmp2 as table(RowNo bigint,name varchar(max))
insert into #tmp1(name)select * from (SELECT name = T.c.value('.','varchar(max)')FROM #X1.nodes('/root/s') T(c)) T
declare #num as int;
set #num = (select count(*) from #tmp1);
-- Permutations of #t
with T (name, level) as(select convert(varchar(max), name), level=1 from #tmp1 union all select convert(varchar(max),t1.name+' '+T.name),level+1
from #tmp1 t1,T where level < #num and charindex(t1.name,T.name) = 0)
insert into #tmp2(RowNo,name)select RowNo = Row_Number() over (order by name), name from T where level = #num
SET #hit= isnull((select tc.name from #tmp2 t inner join **YourTableName** tc on t.name=tc.name),'')
SET #hit=concat('Full Name Matched with:',#hit)
IF len(#hit)>0 --#hit<>''
SET #hit=concat('FullName Matched with:',#hit)
Else
BEGIN
SET #hit=concat('No FullName Matched with:',#hit)
end
print #hit
Note : In 'YourTableName', 'Name' column contain fullname
I have one complex query in SQL which is taking long time, i.e. more than 1 min, to produce the results due to Row_Number() in SQL. I am unable to find a better option in place of that. Below is my SQL query.
Declare #AgreementNumber nvarchar(500)
Declare #SerialNo nvarchar(100)
Declare #EmailId nvarchar(1000)
Declare #CountryId nvarchar(10)
Declare #SaleType tinyint
Declare #CompanyName nvarchar(255)
Declare #PONo numeric(18,0)
Declare #Status tinyint
Declare #POCDeliveryType nvarchar(10)
Declare #FromDate datetime
Declare #ToDate datetime
Declare #CurrentPage numeric
Declare #PageSize numeric
Declare #FileId numeric(18,0)
Declare #PurchaseOrg nvarchar(4)
set #AgreementNumber =''
set #SerialNo =''
set #EmailId =''
set #CountryId ='0014'
set #SaleType=0
set #CompanyName =''
set #PONo= 0
set #Status =0
set #POCDeliveryType =''
set #FromDate =''
set #ToDate =''
set #CurrentPage =1
set #PageSize =100000
set #FileId =0
set #PurchaseOrg =''
----For Paging---------------------------------------------------------------------
Declare #TotalRecord numeric
Declare #StartRow numeric
Declare #EndRow numeric
Set #StartRow=(#PageSize * (#CurrentPage-1)) + 1
Set #EndRow=(#PageSize * (#CurrentPage))
-----------------------------------------------------------------------------------
Select #TotalRecord=Count(*)
From OrderHeader OH inner join OrderLine OL on OH.OrderID=OL.OrderId
Where (OH.CountryId=#CountryId or ISNULL(#CountryId,'')='') and
(OH.PurchaseOrg=#PurchaseOrg or ISNULL(#PurchaseOrg,'')='') and
(SaleType=#SaleType or ISNULL(#SaleType,0)=0) and
(CompanyName like '%'+ isnull(#CompanyName,'') + '%'or isnull(#CompanyName,'')='')and
(PurchaseOrderNo = #PONo or isnull(#PONo,0)=0)and
(OL.Status=#Status or ISNULL(#Status,0)=0) and
(POCDeliveryPreference=#POCDeliveryType or ISNULL(#POCDeliveryType,'')='') and
((CONVERT(VARCHAR(12),OH.Created,112)>=CONVERT(VARCHAR(12),#FromDate,112))or (Isnull(#FromDate,'')=''))and
(CONVERT(VARCHAR(12),OH.Created,112)<=CONVERT(VARCHAR(12),#ToDate,112)or (Isnull(#ToDate,'')='')) and
(OL.SerialNumber like '%'+#SerialNo+'%' or ISNULL(#SerialNo,'') ='') and
(OL.AgreementNumber like '%'+#AgreementNumber+'%' or ISNULL(#AgreementNumber,'') ='') and
(OH.EmailAddress like '%'+#EmailId+'%' or ISNULL(#EmailId,'') ='') and
(OH.FileId=#FileId or isnull(#FileId,0)=0)
Select *, #TotalRecord as TotalRecord From
(
**Select ROW_NUMBER() OVER
(
Order By OH.Created Desc
)as Row**,OH.OrderID,ISNULL(CustomerId,'') as CustomerId,ISNULL(OH.CountryId,'') as CountryId,SaleType,HwPurchaseDate,ISNULL(AddressLine1,'') as
AddressLine1,ISNULL(AddressLine2,'') as AddressLine2,ISNULL(City,'') as City,ISNULL([State],'') as [State],ISNULL(Zip,'') as Zip,
ISNULL(County,'') as County,ISNULL(CompanyName,'') as CompanyName,ISNULL(EmailAddress,'') as EmailId,ISNULL(FirstName,'') as FirstName,
ISNULL(LastName,'') as LastName,ISNULL(PrimaryPhone,'') as Phone,ISNULL(PurchaseOrderNo,0) as POno,ISNULL(OL.[Status],0) as [Status],POCDeliveryPreference,
POCLanguage,CustPOReference,ISNULL(CurrencyCode,'') as CurrencyCode,TransactionId,ISNULL(OH.DeliveryStatus,0) as DeliveryStatus,
isnull(IPAddress,'') as IPAddress, ISNULL(InTouchSessionId,'') as InTouchSessionId, ISNULL(InTouchUserId,'') as InTouchUserId,
ISNULL(SourceSystem,0) as SourceSystem,SalesOrderDate,OH.Created,isnull(OL.SerialNumber,'') as SerialNumber,ISNULL(OL.AgreementNumber,'') as AgreementNumber,
ISNULL(OL.PurchaseOrderNoLineLevel,'') as PurchaseOrderNoLineLevel,ISNULL(OL.ProductName,'') as ProductName,ISNULL(OL.OrderQty,0) as OrderQty,
ISNULL(OL.ManufPartNo,'') as ManufPartNo,isnull(OL.VendorStatus,'') as VendorStatus, isnull(OL.StatusRemark, '') as StatusRemark
From OrderHeader OH inner join OrderLine OL on OH.OrderID=OL.OrderId
Where (OH.CountryId=#CountryId or ISNULL(#CountryId,'')='') and
(OH.PurchaseOrg=#PurchaseOrg or ISNULL(#PurchaseOrg,'')='') and
(SaleType=#SaleType or ISNULL(#SaleType,0)=0) and
(CompanyName like '%'+ isnull(#CompanyName,'') + '%'or isnull(#CompanyName,'')='')and
(PurchaseOrderNo = #PONo or isnull(#PONo,0)=0)and
(OL.Status=#Status or ISNULL(#Status,0)=0) and
(POCDeliveryPreference=#POCDeliveryType or ISNULL(#POCDeliveryType,'')='') and
((CONVERT(VARCHAR(12),OH.Created,112)>=CONVERT(VARCHAR(12),#FromDate,112))or (Isnull(#FromDate,'')=''))and
(CONVERT(VARCHAR(12),OH.Created,112)<=CONVERT(VARCHAR(12),#ToDate,112)or (Isnull(#ToDate,'')='')) and
(OL.SerialNumber like '%'+#SerialNo+'%' or ISNULL(#SerialNo,'') ='') and
(OL.AgreementNumber like '%'+#AgreementNumber+'%' or ISNULL(#AgreementNumber,'') ='') and
(OH.EmailAddress like '%'+#EmailId+'%' or ISNULL(#EmailId,'') ='') and
(OH.FileId=#FileId or isnull(#FileId,0)=0)
)
as RowResults
Where Row between #StartRow AND #EndRow
I have highlighted that part which is taking so long time.
OH.CountryId = #CountryId or ISNULL(#CountryId, '') = '')
Generally these sorts of things should be avoided. It prevents SQL Server from performing an index seek and instead performs an index scan. Can you use dynamic SQL instead and include in the where OH.CountryId = #CountryId only when its specified?
Replace
((CONVERT(VARCHAR(12),OH.Created,112)>=CONVERT(VARCHAR(12),#FromDate,112))
(CONVERT(VARCHAR(12),OH.Created,112)<=CONVERT(VARCHAR(12),#ToDate,112)
by Cast(OH.Created as date)>=Cast(#FromDate as date)
Cast(OH.Created as date)<=Cast(#FromDate as date)
the convert creating a plan that is not the best.
There are lots of issue in query itself
(1) Using same query twice
(2) trying to catch all query(inefficiently ) that can produce horrible plan
(3) Using predicate like OH.EmailAddress like '%'+#EmailId+'%'
(4) inefficient paging
Declare #AgreementNumber nvarchar(500)
Declare #SerialNo nvarchar(100)
Declare #EmailId nvarchar(1000)
Declare #CountryId nvarchar(10)
Declare #SaleType tinyint
Declare #CompanyName nvarchar(255)
Declare #PONo numeric(18,0)
Declare #Status tinyint
Declare #POCDeliveryType nvarchar(10)
Declare #FromDate datetime
Declare #ToDate datetime
Declare #CurrentPage numeric
Declare #PageSize numeric
Declare #FileId numeric(18,0)
Declare #PurchaseOrg nvarchar(4)
set #AgreementNumber =''
set #SerialNo =''
set #EmailId =''
set #CountryId ='0014'
set #SaleType=0
set #CompanyName =''
set #PONo= 0
set #Status =0
set #POCDeliveryType =''
set #FromDate =''
set #ToDate =''
set #CurrentPage =1
set #PageSize =100000
set #FileId =0
set #PurchaseOrg =''
----For Paging---------------------------------------------------------------------
Declare #TotalRecord numeric
Declare #StartRow numeric
Declare #EndRow numeric
Set #StartRow=(#PageSize * (#CurrentPage-1)) + 1
Set #EndRow=(#PageSize * (#CurrentPage))
-----------------------------------------------------------------------------------
--Select #TotalRecord=Count(*)
--From OrderHeader OH inner join OrderLine OL on OH.OrderID=OL.OrderId
--Where (OH.CountryId=#CountryId or ISNULL(#CountryId,'')='') and
--(OH.PurchaseOrg=#PurchaseOrg or ISNULL(#PurchaseOrg,'')='') and
-- (SaleType=#SaleType or ISNULL(#SaleType,0)=0) and
-- (CompanyName like '%'+ isnull(#CompanyName,'') + '%'or isnull(#CompanyName,'')='')and
-- (PurchaseOrderNo = #PONo or isnull(#PONo,0)=0)and
-- (OL.Status=#Status or ISNULL(#Status,0)=0) and
-- (POCDeliveryPreference=#POCDeliveryType or ISNULL(#POCDeliveryType,'')='') and
-- ((CONVERT(VARCHAR(12),OH.Created,112)>=CONVERT(VARCHAR(12),#FromDate,112))or (Isnull(#FromDate,'')=''))and
-- (CONVERT(VARCHAR(12),OH.Created,112)<=CONVERT(VARCHAR(12),#ToDate,112)or (Isnull(#ToDate,'')='')) and
-- (OL.SerialNumber like '%'+#SerialNo+'%' or ISNULL(#SerialNo,'') ='') and
-- (OL.AgreementNumber like '%'+#AgreementNumber+'%' or ISNULL(#AgreementNumber,'') ='') and
-- (OH.EmailAddress like '%'+#EmailId+'%' or ISNULL(#EmailId,'') ='') and
-- (OH.FileId=#FileId or isnull(#FileId,0)=0)
With RowResults as
(
Select ROW_NUMBER() OVER
(
Order By OH.Created Desc
)as Row ,OH.OrderID,ISNULL(CustomerId,'') as CustomerId,ISNULL(OH.CountryId,'') as CountryId,SaleType,HwPurchaseDate,ISNULL(AddressLine1,'') as
AddressLine1,ISNULL(AddressLine2,'') as AddressLine2,ISNULL(City,'') as City,ISNULL([State],'') as [State],ISNULL(Zip,'') as Zip,
ISNULL(County,'') as County,ISNULL(CompanyName,'') as CompanyName,ISNULL(EmailAddress,'') as EmailId,ISNULL(FirstName,'') as FirstName,
ISNULL(LastName,'') as LastName,ISNULL(PrimaryPhone,'') as Phone,ISNULL(PurchaseOrderNo,0) as POno,ISNULL(OL.[Status],0) as [Status],POCDeliveryPreference,
POCLanguage,CustPOReference,ISNULL(CurrencyCode,'') as CurrencyCode,TransactionId,ISNULL(OH.DeliveryStatus,0) as DeliveryStatus,
isnull(IPAddress,'') as IPAddress, ISNULL(InTouchSessionId,'') as InTouchSessionId, ISNULL(InTouchUserId,'') as InTouchUserId,
ISNULL(SourceSystem,0) as SourceSystem,SalesOrderDate,OH.Created,isnull(OL.SerialNumber,'') as SerialNumber,ISNULL(OL.AgreementNumber,'') as AgreementNumber,
ISNULL(OL.PurchaseOrderNoLineLevel,'') as PurchaseOrderNoLineLevel,ISNULL(OL.ProductName,'') as ProductName,ISNULL(OL.OrderQty,0) as OrderQty,
ISNULL(OL.ManufPartNo,'') as ManufPartNo,isnull(OL.VendorStatus,'') as VendorStatus, isnull(OL.StatusRemark, '') as StatusRemark
From OrderHeader OH inner join OrderLine OL on OH.OrderID=OL.OrderId
Where (OH.CountryId=#CountryId or ISNULL(#CountryId,'')='') and
(OH.PurchaseOrg=#PurchaseOrg or ISNULL(#PurchaseOrg,'')='') and
(SaleType=#SaleType or ISNULL(#SaleType,0)=0) and
(CompanyName like '%'+ isnull(#CompanyName,'') + '%'or isnull(#CompanyName,'')='')and
(PurchaseOrderNo = #PONo or isnull(#PONo,0)=0)and
(OL.Status=#Status or ISNULL(#Status,0)=0) and
(POCDeliveryPreference=#POCDeliveryType or ISNULL(#POCDeliveryType,'')='') and
((CONVERT(VARCHAR(12),OH.Created,112)>=CONVERT(VARCHAR(12),#FromDate,112))or (Isnull(#FromDate,'')=''))and
(CONVERT(VARCHAR(12),OH.Created,112)<=CONVERT(VARCHAR(12),#ToDate,112)or (Isnull(#ToDate,'')='')) and
(OL.SerialNumber like '%'+#SerialNo+'%' or ISNULL(#SerialNo,'') ='') and
(OL.AgreementNumber like '%'+#AgreementNumber+'%' or ISNULL(#AgreementNumber,'') ='') and
(OH.EmailAddress like '%'+#EmailId+'%' or ISNULL(#EmailId,'') ='') and
(OH.FileId=#FileId or isnull(#FileId,0)=0)
)
Select max (Row) , * FRom RowResults
Where Row between #StartRow AND #EndRow
option (recompile)
-- quick fix only
-- --if using SQL SERVER 2012
-- OFFSET #StartRow ROWS
--FETCH NEXT #EndRow -#StartRow ROWS ONLY
--if ans still not gaining performance we wold like to see actual exection plan
--(1) Using same query twice DONE
--(2) trying to catch all query(inefficiently ) that can produce horrible plan DONE by option recompile (still you need to understand this use dynamic query if you are not exposed to sql injection)
--(3) Using predicate like OH.EmailAddress like '%'+#EmailId+'%' -- you need to adress this
--(4) inefficient paging -- fetch next is quite fast that row_num .