Related
UPDATE QUERY TAKING MORE TIME. IS THERE ANY OTHER WAY TO WRITE BELOW QUERY WITHOUT TOP 1? LIKE USING RANK OR ROWNUMBER FUNCTIONS?
SELECT proddiv,
prodstl,
prodcode,
lablcode,
proddim,
proddiv AS PRD_DIV,
prodstl AS PRD_PRODSTL,
prodcode AS PRDCOLOR,
label_code AS PRDlbl,
proddim AS par_dim,
0 AS low_level,
0 AS smuh_pkey,
IDENTITY(int) AS prdkey,
list_price
INTO #brandsdata
FROM products WITH (nolock)
DECLARE #Max INT = 30,
#x INT = 0
WHILE ( #x < 30 )
BEGIN
UPDATE t
SET smuh_pkey = (SELECT TOP 1 prdkey
FROM customers WITH (nolock)
WHERE ( proddiv = ''
OR proddiv = t.proddiv )
AND ( prodstl = ''
OR prodstl = t.prodstl )
AND ( prodcode = ''
OR prodcode = t.prodcode )
AND ( lablcode = ''
OR lablcode = t.lablcode )
AND ( proddim = ''
OR proddim = t.proddim )
AND prod_type = ''
AND active_ok = 'Y'
ORDER BY brand_name,
brand_type DESC)
FROM #brandsdata t
WHERE smuh_pkey = 0
AND low_level = #x
SET #x = #x + 1
END
THANKS IN ADVANCE.
Try something like this.
;with c as (
select c.prdKey, c.proddiv, c.prodstl, c.prodcode, c.lablcode, c.proddim,
ROW_NUMBER() over (
partition by c.proddiv, c.prodstl, c.prodcode, c.lablcode, c.proddim
order by c.brand_name, c.brand_type DESC) rn
from customers c
where prod_type = '' and
active_ok = 'Y'
)
update t
set smuh_pkey = c.prdKey
from #brandsdata t
inner join c
on ( c.proddiv = '' OR c.proddiv = t.proddiv )
AND ( c.prodstl = '' OR c.prodstl = t.prodstl )
AND ( c.prodcode = '' OR c.prodcode = t.prodcode )
AND ( c.lablcode = '' OR c.lablcode = t.lablcode )
AND ( c.proddim = '' OR c.proddim = t.proddim )
where c.rn = 1
I think it will not be enough for 100% of the cases, because if you can have multiple combinations of empty string with not empty, you could get different results.
then you could fine tune
I have over 50 stored procedures that I need to convert so that I can use a dynamic whereclause in them. My select statemement looks like this in SQL. I need to change this to a varchar(max) string and use Execute(#SQL) or sp_executesql #SQL
Is there any tool online or purchased that can convert this where clause into the proper string format with the correct escape sequences for the #Parameters?
;WITH TempResult AS(SELECT
DataDt
,EffDt
,SettlementDt
,BankId
,SeqNum
,DeleteFlag
,LoanNum
,BondLoanSaleType
,PurchaseProceedsAmt
,SettledPrinBal
,IntRecMiscAmt
,BuydownCashClearingAmt
,ARClearingDAPAmt
,ARCashClearingAmt
,ARSuspenseAmt
,ImpoundsSoldLoansAmt
,BondCommitmentFeesAmt
,SRPAmt
,OtherFeeAmt
,ActiveFlagBit = case ActiveFlagBit when 1 then 1 else 0 end
,UploadByCfcUserId
,UploadDtTm
,UploadedFileName
,ApprovedFlagBit = case ApprovedFlagBit when 1 then 1 else 0 end
,ApproveRejectByCfcUserId
,ApproveRejectDtTm
,ApprovalTaskId
,ArchiveDtTm
FROM guiUploadBondLoanSales u (nolock)
WHERE
(#LoanList.exist('/NewDataSet/Table1') = 0 or LoanNum in (select LoanNum from #tmpLoan))
and (#DataDtTo = '01/01/1900' or DataDt between #DataDtFrom and #DataDtTo)
and (#SettlementDtTo = '01/01/1900' or SettlementDt between #SettlementDtFrom and #SettlementDtTo)
and (#ShowOnlyLatest = 0 or (ActiveFlagBit = 1 and ApprovedFlagBit = 1 and u.DataDt =
(select max(DataDt) from guiUploadBondLoanSales u1 (nolock)
where u1.LoanNum = u.LoanNum and u1.ActiveFlagBit = 1 and u1.ApprovedFlagBit = 1)))
and (#TaskId = 0 or ApprovalTaskId = #TaskId)
and (#FileName = '' or UploadedFileName like '%' + #FileName + '%')
and (#UploadedByUsers.exist('/NewDataSet/Table1') = 0 or UploadByCfcUserId in (select UploadedByUsers from #UploadedByUsers))
and (#ApprovedByUsers.exist('/NewDataSet/Table1') = 0 or ApproveRejectByCfcUserId in (select ApprovedByUsers from #ApprovedByUsers))
and (#UploadDtTo = '01/01/1900' or UploadDtTm between #UploadDtFrom and #UploadDtTo)
and (#ApprovedDtTo = '01/01/1900' or ApproveRejectDtTm between #ApprovedDtFrom and #ApprovedDtTo)
and (#HideArchive = 0 or u.ArchiveDtTm = '1/1/1900' )
), TempCount AS ( SELECT COUNT(*) AS MaxRows FROM TempResult) SELECT *, TempCount.MaxRows FROM TempResult, TempCount ORDER BY TempResult.UploadDtTm OFFSET #OFFSET ROWS FETCH NEXT #FETCH ROWS ONLY OPTION(RECOMPILE)
I can't seem to make my SP works:
ALTER PROCEDURE [dbo].[TestSP]
#participant_role nvarchar(max) = null,
#active int,
#inactive int
AS
BEGIN
select * from participant_list where participant_role = ISNULL(#participant_role, participant_role)
and
case when #active = 0 then ((effective_end_date IS NULL) or (effective_end_date > CURRENT_DATE))
case when #inactive = 0 then ((effective_end_date IS NOT NULL) or (effective_end_date < CURRENT_DATE))
ELSE
--Return everything
END
What happen is, if the #active is 0, the query should include the condition ((effective_end_date IS NULL) or (effective_end_date > CURRENT_DATE))
Like wise, if #inactive is 0, the condition should include ((effective_end_date IS NOT NULL) or (effective_end_date < CURRENT_DATE))
And if both #active and #inactive are NOT 0, then it should return everything (no condition for this part). How do I make it work?
There seems to be a particular affliction where people discover SQL's CASE expression and seem to immediately stop thinking about simpler boolean operators:
select * from participant_list
where participant_role = ISNULL(#participant_role, participant_role)
and
(
(
#active = 0 and (
(effective_end_date IS NULL) or
(effective_end_date > CURRENT_DATE)
)
) or
(
#inactive = 0 and effective_end_date < CURRENT_DATE
) or
( #active = 1 and #inactive = 1)
)
SELECT *
FROM mytable
WHERE ...
AND
CASE
WHEN #active = 0 AND ((effective_end_date IS NULL) or (effective_end_date > CURRENT_DATE)) THEN
1
WHEN #inactive = 0 AND ((effective_end_date IS NOT NULL) or (effective_end_date < CURRENT_DATE)) THEN
1
ELSE
1
END = 1
select * from participant_list
where participant_role = ISNULL(#participant_role, participant_role)
and
(
(#active = 0 and (effective_end_date IS NULL or effective_end_date > CURRENT_DATE))
or
(#inactive = 0 and (effective_end_date IS NOT NULL or effective_end_date < CURRENT_DATE))
or
(#active != 0 and #active != 0)
)
using case
select * from participant_list
where (#participant_role IS NOT NULL AND participant_role = #participant_role)
and 1 = (case when #active = 0 AND (effective_end_date IS NULL or (effective_end_date > GETDATE()))
then 1
when #inactive = 0 AND (effective_end_date IS NOT NULL or (effective_end_date < GETDATE()) )
then 1
WHEN #active = 0 AND #inactive = 0
THEN 1
else 0 end)
Stored procedure is taking 5 minutes to execute, but if query of which I have written procedure then it will take on 4 sec. I did google and find parameters sniffing for improving procedures performance so implemented that and now it still taking 3 minutes.
What should I do?
Thanks
Atul yadav
Here is my stored procedure code:
CREATE PROCEDURE [dbo].[get_all]
#para_factor_id int,
#para_factor_client_id int,
#para_factor_customer_id int,
#para_invoice_date_from date,
#para_invoice_date_to date,
#para_invoice_amount_from decimal(18, 2),
#para_invoice_amount_to decimal(18, 2),
#para_invoice_id int,
#para_schedule_number varchar(400),
#para_invoice_number varchar(400),
#para_schedule_id int,
#para_invoice_status_id varchar(50),
#para_marked_for_printing bit,
#para_user_id int,
#para_role_id int,
#para_current_date date,
#para_approval_status_id int = 0,
#para_is_verified int = 0,
#para_load_number varchar(400) = ''
WITH EXEC AS CALLER
AS
BEGIN
DECLARE #var_invoice_order INT
= (SELECT invoice_order
FROM factor_default_settings fds
WHERE fds.factor_id = #para_factor_id);
DECLARE #v_factor_id INT;
DECLARE #v_factor_client_id INT;
DECLARE #v_factor_customer_id INT;
DECLARE #v_invoice_date_from DATETIME;
DECLARE #v_invoice_date_to DATETIME;
DECLARE #v_invoice_amount_from DECIMAL (18, 2);
DECLARE #v_invoice_amount_to DECIMAL (18, 2);
DECLARE #v_invoice_id INT;
DECLARE #v_schedule_number VARCHAR (400);
DECLARE #v_invoice_number VARCHAR (400);
DECLARE #v_schedule_id INT;
DECLARE #v_invoice_status_id VARCHAR (50);
DECLARE #v_marked_for_printing BIT;
DECLARE #v_user_id INT;
DECLARE #v_role_id INT;
DECLARE #v_current_date DATETIME;
DECLARE #v_approval_status_id INT;
DECLARE #v_is_verified INT;
DECLARE #v_load_number VARCHAR (400);
SET #v_factor_id = #para_factor_id;
SET #v_factor_client_id = #para_factor_client_id;
SET #v_factor_customer_id = #para_factor_customer_id;
SET #v_invoice_date_from = #para_invoice_date_from;
SET #v_invoice_date_to = #para_invoice_date_to;
SET #v_invoice_amount_from = #para_invoice_amount_from;
SET #v_invoice_amount_to = #para_invoice_amount_to;
SET #v_invoice_id = #para_invoice_id;
SET #v_schedule_number = #para_schedule_number;
SET #v_invoice_number = #para_invoice_number;
SET #v_schedule_id = #para_schedule_id;
SET #v_invoice_status_id = #para_invoice_status_id;
SET #v_marked_for_printing = #para_marked_for_printing;
SET #v_user_id = #para_user_id;
SET #v_role_id = #para_role_id;
SET #v_current_date = #para_current_date;
SET #v_approval_status_id = #para_approval_status_id;
SET #v_is_verified = #para_is_verified;
SET #v_load_number = #para_load_number;
SET NOCOUNT ON;
SELECT TOP 300
inv.factor_id,
inv.invoice_id,
inv.schedule_id,
inv.term_id,
inv.factor_client_id,
inv.factor_customer_id,
inv_trn.client_name,
SUBSTRING (inv_trn.client_name, 1, 10) AS client_name_10,
inv_trn.customer_name,
SUBSTRING (inv_trn.customer_name, 1, 10) AS customer_name_10,
sch.schedule_number,
sch.payment_method_id,
inv.invoice_number,
inv.po_number,
inv.invoice_date,
inv.est_days_out,
(CASE
WHEN inv.manually_flagged = 1
THEN
1
ELSE
CASE
WHEN inv.flag_days > 0
AND inv.discount_calculation_date >
CONVERT (DATE, '1900/01/01')
THEN
CASE
WHEN DATEDIFF (DAY,
inv.discount_calculation_date,
#v_current_date) > inv.flag_days
THEN
1
ELSE
0
END
ELSE
0
END
END)
AS flag_days_icon,
inv.flag_days,
inv.float_days,
DATEADD (DAY, inv.est_days_out, inv.invoice_date) AS due_date,
inv.invoice_amount,
inv.credit_limit_exceeded_by_client,
inv.po_duplication_status,
inv.advance_amount,
inv.advance_calculation_decision_id,
inv.advance_percent,
inv.advance_calculation_formula,
(CASE inv.deduct_discount_from_advance
WHEN 1 THEN 'Yes'
ELSE 'No'
END)
AS deduct_discount_from_advance,
deduct_discount_from_advance AS deduct_discount,
inv.verified,
inv.estimated_advance_date,
inv_trn.notes_count,
inv.net_term,
inv_trn.total_adjustment_amount,
inv.approval_status_id,
inv_apr_stat.approval_status,
sch.submitted,
sch.made_by_client,
sch.submitted_by_client,
sch.authorized_by_client,
inv.invoice_status_id,
inv_st.invoice_status,
inv.verified,
inv.client_customer_id,
CAST (inv_trn.attachment_count AS INT) AS attachment_count,
ROUND ( (inv.advance_amount - inv_trn.advance_discount), 2)
AS payment_amount,
(inv_trn.escrow_advance - pmt.total_escrow_amount)
AS escrow_amount,
inv_trn.dilution_type_id,
inv_trn.dilution,
inv_trn.dilution_amount,
inv_trn.dilution_term_rate_id,
inv_trn.po_deduction_type_id,
inv.po_id,
inv.fuel_advance,
inv.fuel_adv_with_adj,
inv.dispute
FROM invoices inv
JOIN dbo.fun_get_client_list_profile_management (#v_factor_id,
#v_user_id,
#v_role_id,
1) fun_cl
ON inv.factor_client_id = fun_cl.factor_client_id
JOIN factor_customers fact_cust
ON inv.factor_customer_id = fact_cust.factor_customer_id
AND ( inv.factor_customer_id = #v_factor_customer_id
OR #v_factor_customer_id = 0)
JOIN factor_clients fact_cl
ON inv.factor_client_id = fact_cl.factor_client_id
JOIN client_customers cl_cust
ON inv.client_customer_id = cl_cust.client_customer_id
JOIN invoice_transaction_values inv_trn
ON inv.invoice_id = inv_trn.invoice_id
JOIN schedules sch
ON inv.schedule_id = sch.schedule_id
JOIN invoice_total_payments pmt
ON inv.invoice_id = pmt.invoice_id
AND pmt.payment_type_id = 1
JOIN invoice_approval_status inv_apr_stat
ON inv.approval_status_id = inv_apr_stat.approval_status_id
JOIN invoice_status inv_st
ON inv.invoice_status_id = inv_st.invoice_status_id
LEFT JOIN (SELECT inv_prop.invoice_id,
inv_prop.mark_for_printing
FROM invoice_properties inv_prop
JOIN invoices inv
ON inv_prop.invoice_id = inv.invoice_id
JOIN factor_clients fact_cl
ON inv.factor_client_id =
fact_cl.factor_client_id
JOIN factor_customers fact_cust
ON inv.factor_customer_id =
fact_cust.factor_customer_id
WHERE inv.factor_id = #v_factor_id
AND ( inv.factor_client_id =
#v_factor_client_id
OR #v_factor_client_id = 0)
AND ( inv.factor_customer_id =
#v_factor_customer_id
OR #v_factor_customer_id = 0)
AND fact_cl.active = 1
AND fact_cust.active = 1) AS inv_prop
ON inv_prop.invoice_id = inv.invoice_id
LEFT JOIN invoice_custom_field_values inv_cust_fld_val
ON inv.invoice_id = inv_cust_fld_val.invoice_id
AND inv_cust_fld_val.custom_field_id = 4
WHERE inv.factor_id = #v_factor_id
AND ( inv.factor_client_id = #v_factor_client_id
OR #v_factor_client_id = 0)
AND ( inv.factor_customer_id = #v_factor_customer_id
OR #v_factor_customer_id = 0)
AND fact_cl.active = 1
AND fact_cust.active = 1
AND cl_cust.active = 1
AND inv.invoice_amount BETWEEN #v_invoice_amount_from
AND #v_invoice_amount_to
AND inv.invoice_date BETWEEN #v_invoice_date_from
AND #v_invoice_date_to
AND (inv.invoice_id = #v_invoice_id OR #v_invoice_id = 0)
AND (inv.schedule_id = #v_schedule_id OR #v_schedule_id = 0)
AND sch.schedule_number LIKE '%' + #v_schedule_number + '%'
AND inv.invoice_number LIKE '%' + #v_invoice_number + '%'
AND ( inv.invoice_status_id IN
(SELECT items
FROM dbo.fun_split_string (#v_invoice_status_id,
','))
OR #v_invoice_status_id = '')
-- AND ( ISNULL (inv_prop.mark_for_printing,
-- #v_marked_for_printing) = 0
-- OR #v_marked_for_printing = 0)
AND ( ISNULL (inv_prop.mark_for_printing, 0) =
#v_marked_for_printing
OR #v_marked_for_printing = 0)
AND ( ( #v_role_id IN (2, 6)
AND ( sch.submitted_by_client = 1
OR sch.made_by_client = 0))
OR (#v_role_id IN (3, 10)))
AND ( inv.approval_status_id = #v_approval_status_id
OR #v_approval_status_id = 0)
AND (#v_is_verified = 0 OR inv.verified = 1)
AND ( (inv_cust_fld_val.value LIKE '%' + #v_load_number + '%')
OR #v_load_number = '')
AND inv.approval_status_id IN (1,2)
ORDER BY CASE WHEN #var_invoice_order = 1 THEN inv.invoice_date END ASC,
CASE WHEN #var_invoice_order = 1 THEN inv.invoice_id END ASC,
CASE WHEN #var_invoice_order = 2 THEN inv.invoice_date END DESC,
CASE WHEN #var_invoice_order = 2 THEN inv.invoice_id END DESC
END
There are few things you need to change in the stored proc first.
1) implement indexes (if not there).
2) Do not use function in join "dbo.fun_get_client_list_profile_management"
Instead of that you need to create a temp table/table variable and populate that with dbo.fun_get_client_list_profile_management and then join the temp table/table variable with the actual query. Because when you use function instead of table the function is called for each row results.
3) Same thing you need to do for "inv_prop". Populate a temp table/ table variable with that subquery and then use that table in actual query.
4) Same thing goes for
inv.invoice_status_id IN
(SELECT items
FROM dbo.fun_split_string (#v_invoice_status_id,
','))
OR #v_invoice_status_id = ''
Change it to table variables and instead of "IN" use join
Change those things and let us know the improvement.
It could be that you have a bad plan in the cache for that stored procedure. Recompile it and see if the performance is comparable to the query.
EXEC sp_recompile N'dbo.get_all';
I'm working on an advanced search sproc and would like to know if it is possible for a portion of my select to be included or not based on a parameter. I could use an IF ELSE on my parameter, but I already have one for another parameter, and that seems like a lot of code duplication.
-- My advanced search function allows a user to specify various parameters. The basic search can be EXACT or not (contains vs freetext - first if), and other parameters (AND) can be specified. Specific keywords can also be selected as well (intersect).
My issue is that when #Keywords is null, I don't want to include the final INTERSECT SELECT ... portion of the code at the bottom of my example. Is there a quick way to do this without adding another IF ELSE in the top and bottom queries? Let me know if you need more detailed information.
declare #SearchTerms nvarchar(4000)
declare #GalleryId int
declare #Keywords nvarchar(4000)
declare #ExactWord int
declare #BeginDateUpload datetime
declare #EndDateUpload datetime
declare #BeginDateTaken datetime
declare #EndDateTaken datetime
declare #MinFileSize int
declare #MaxFileSize int
declare #AlbumType bit
declare #ImageType int
declare #AudioType int
declare #OtherType int
declare #VideoType int
set #SearchTerms = 'tulips'
set #GalleryId = 1
set #Keywords = null -- 'st-jean'
set #ExactWord = null
set #BeginDateUpload = null
set #EndDateUpload = null
set #BeginDateTaken = null
set #EndDateTaken = null
set #MinFileSize = null
set #MaxFileSize = null
set #AlbumType = 1
set #ImageType = 1
set #AudioType = 1
set #OtherType = 1
set #VideoType = 1
IF ISNULL(#ExactWord, 0) = 1
BEGIN
[... snip ...]
END
ELSE
select t1.* from (
SELECT 'm' as objType, m.MediaObjectId
FROM gs_mediaObjectMetadata md
INNER JOIN dbo.[gs_MediaObject] m
ON md.FKMediaObjectId = m.MediaObjectId
INNER JOIN dbo.[gs_Album] a
ON a.AlbumId = m.FKAlbumId
WHERE FREETEXT (value, #SearchTerms)
AND a.FKGalleryId = #GalleryId
AND (m.DateAdded >= ISNULL(#BeginDateUpload, m.DateAdded))
AND (m.DateAdded <= ISNULL(#EndDateUpload, m.DateAdded))
AND (m.DateTaken is NULL OR m.DateTaken >= ISNULL(#BeginDateTaken, m.DateTaken))
AND (m.DateTaken is NULL OR m.DateTaken <= ISNULL(#EndDateTaken, m.DateTaken))
AND (m.OriginalSizeKB >= ISNULL(#MinFileSize, m.OriginalSizeKB))
AND (m.OriginalSizeKB <= ISNULL(#MaxFileSize, m.OriginalSizeKB))
AND((m.FKMediaObjectTypeId = ISNULL(#ImageType, 0))
OR (m.FKMediaObjectTypeId = ISNULL(#AudioType, 0))
OR (m.FKMediaObjectTypeId = ISNULL(#VideoType, 0))
OR (m.FKMediaObjectTypeId = ISNULL(#OtherType, 0)))
union
SELECT 'm' as objType, m.MediaObjectId
FROM dbo.[gs_MediaObject] m
INNER JOIN dbo.[gs_Album] a
ON a.AlbumId = m.FKAlbumId
WHERE FREETEXT ((m.Title, OriginalFilename), #SearchTerms)
AND a.FKGalleryId = #GalleryId
AND (m.DateAdded >= ISNULL(#BeginDateUpload, m.DateAdded))
AND (m.DateAdded <= ISNULL(#EndDateUpload, m.DateAdded))
AND (m.DateTaken is NULL OR m.DateTaken >= ISNULL(#BeginDateTaken, m.DateTaken))
AND (m.DateTaken is NULL OR m.DateTaken <= ISNULL(#EndDateTaken, m.DateTaken))
AND (m.OriginalSizeKB >= ISNULL(#MinFileSize, m.OriginalSizeKB))
AND (m.OriginalSizeKB <= ISNULL(#MaxFileSize, m.OriginalSizeKB))
AND((m.FKMediaObjectTypeId = ISNULL(#ImageType, 0))
OR (m.FKMediaObjectTypeId = ISNULL(#AudioType, 0))
OR (m.FKMediaObjectTypeId = ISNULL(#VideoType, 0))
OR (m.FKMediaObjectTypeId = ISNULL(#OtherType, 0)))
) t1
--IF #Keywords != null -- conditional intersect
intersect
SELECT 'm' as objType, m.MediaObjectId
FROM dbo.[gs_MediaObject] m
INNER JOIN dbo.[gs_Album] a
ON a.AlbumId = m.FKAlbumId
left join dbo.gs_MediaObjectMetadata md
on m.MediaObjectId = md.FKMediaObjectId
WHERE FREETEXT ((m.Title, OriginalFilename), #SearchTerms)
AND a.FKGalleryId = #GalleryId
AND (m.DateAdded >= ISNULL(#BeginDateUpload, m.DateAdded))
AND (m.DateAdded <= ISNULL(#EndDateUpload, m.DateAdded))
AND (m.DateTaken is NULL OR m.DateTaken >= ISNULL(#BeginDateTaken, m.DateTaken))
AND (m.DateTaken is NULL OR m.DateTaken <= ISNULL(#EndDateTaken, m.DateTaken))
AND (m.OriginalSizeKB >= ISNULL(#MinFileSize, m.OriginalSizeKB))
AND (m.OriginalSizeKB <= ISNULL(#MaxFileSize, m.OriginalSizeKB))
AND((m.FKMediaObjectTypeId = ISNULL(#ImageType, 0))
OR (m.FKMediaObjectTypeId = ISNULL(#AudioType, 0))
OR (m.FKMediaObjectTypeId = ISNULL(#VideoType, 0))
OR (m.FKMediaObjectTypeId = ISNULL(#OtherType, 0)))
and UPPER(md.Description) = 'KEYWORDS'
and exists (
SELECT *
FROM dbo.fnSplit(Replace(md.Value, '''', ''''''), ',') split
WHERE split.item in
(SELECT * from dbo.fnSplit(Replace(#Keywords, '''', ''''''), ','))
)
Thank you
What about instead of doing the intersect, try this out in your inner queries : #Keyword is null or .....
and ( #Keywords is null or (UPPER(md.Description) = 'KEYWORDS'
and exists (
SELECT *
FROM dbo.fnSplit(Replace(md.Value, '''', ''''''), ',') split
WHERE split.item in
(SELECT * from dbo.fnSplit(Replace(#Keywords, '''', ''''''), ','))
)
)
)