Related
My SQL statement in SQL Server looks like this:
DECLARE #forecastYear AS varchar(5)
SET #forecastYear = '2020'
DECLARE #versionName AS varchar(25)
SET #versionName = '20201113_wk'
DECLARE #currentMonth AS varchar(2)
SET #currentMonth = (SELECT current_fc_month FROM tbl_current_month)
SELECT f.record_id
, u.it_ops_j_level_abbr_nm
, f.owner_nm
, f.unit_cd
, f.tbm_cd
, f.tower_nm
, f.description_txt
, f.comment_txt
, f.cost_pool_nm
, f.glac_nr
, f.glac_nm
, f.initiative_nm
, f.priority_nm
, f.growth_nm
, f.it_vendor_nm
, f.jan_amt
, f.feb_amt
, f.mar_amt
, f.apr_amt
, f.may_amt
, f.jun_amt
, f.jul_amt
, f.aug_amt
, f.sep_amt
, f.oct_amt
, f.nov_amt
, f.dec_amt
FROM tbl_new_forecast f
INNER JOIN tbl_unit_tree u
ON f.unit_cd = u.dept_id
WHERE f.version_nm = #versionName
AND f.status_cd = 'Approved'
AND f.entry_type = 'Forecast'
AND f.forecast_yr_id = #forecastYear
AND ABS(f.nov_amt)+ABS(f.dec_amt) <> 0
What I want to do is change the last statement in the WHERE clause based on the value in #currentMonth.
Therefore, if #currentMonth = '3' then the last statement would read
AND ABS(f.mar_amt)+ABS(f.apr_amt)+ABS(f.may_amt) <> 0
If #currentMonth = '7' then it would read
AND ABS(f.jul_amt)+ABS(f.aug_amt)+ABS(f.sep_amt) <> 0
I'm having a hard time figuring out how to accomplish this, because I get a SQL error with this syntax:
AND CASE
WHEN #currentMonth = '10' THEN ABS(f.oct_amt)+ABS(f.nov_amt)+ABS(f.dec_amt) <> 0
END
Any help is appreciated!
If you need a solution, a complex WHERE clause is an option. Note, that in T-SQL CASE is an expression, not a statement:
AND (
((#currentMonth = 1) AND (ABS(f.jan_amt) + ABS(f.feb_amt) + ABS(f.mar_amt) <> 0)) OR
((#currentMonth = 2) AND (ABS(f.feb_amt) + ABS(f.mar_amt) + ABS(f.apr_amt) <> 0)) OR
...
((#currentMonth = 10) AND (ABS(f.oct_amt) + ABS(f.nov_amt) + ABS(f.dec_amt) <> 0)) OR
((#currentMonth = 11) AND (ABS(f.nov_amt) + ABS(f.dec_amt) <> 0)) OR
((#currentMonth = 12) AND (ABS(f.dec_amt) <> 0))
)
Use dynamic SQL
DECLARE #month_dependent varchar (500)=' ';
DECLARE #main_query varchar(1000)=' ';
DECLARE #forecastYear AS varchar(5)
SET #forecastYear = '2020'
DECLARE #versionName AS varchar(25)
SET #versionName = '20201113_wk'
DECLARE #currentMonth char(2)
SET #currentMonth = (SELECT current_fc_month FROM tbl_current_month)
If #currentMonth = '3'
BEGIN set #month_dependent=' AND ABS(f.mar_amt)+ABS(f.apr_amt)+ABS(f.may_amt) <> 0 '; END
If #currentMonth = '7'
BEGIN set #month_dependent=' AND ABS(f.jul_amt)+ABS(f.aug_amt)+ABS(f.sep_amt) <> 0 '; END
set #main_query varchar(1000)=' SELECT f.record_id' +
' , u.it_ops_j_level_abbr_nm ' +
-- ' and all the rest of it! ' +
' FROM tbl_new_forecast f '+
' INNER JOIN tbl_unit_tree u '+
' ON f.unit_cd = u.dept_id ' +
' WHERE f.version_nm = '''+ #versionName + ''' '+
' AND f.status_cd = ''Approved'' '+
' AND f.entry_type = ''Forecast'' '+
' AND f.forecast_yr_id = ''' + #forecastYear + ''' '+
#month_dependent
EXECUTE sp_executesql #main_query ;
You can make this really complex by using a WHERE clause with a lot of ors in it:
AND ({first month condition} OR {Second month condition} OR {third month condition})
Etc. Another option is to place this into a stored procedure and use the month as the trigger to determine which statement to run. Depending on how you are running this, it might be a preferred method, as it can abstract out the details from the application (something you will want if you ever decide to normalize this data).
As for trying to use CASE in a WHERE clause, you have it wrong. The CASE WHEN has to equal something. The correct syntax is like:
AND SomeValue = CASE WHEN ...
You cannot simply use case, as a where is looking for equality (=), inequality (<>), and fuzzy values (LIKE). Thus, this does not work.
AND CASE WHEN ...
As an example, this shows something that fires back 1 to get equivalent rows. But you would need all of your conditions in here, which means the WHEN on month and the ABS() would be the entire condition. You then return 1 to indicate "found it". But you are running this as a monthly query, so filtering by the month and then determining the CASE ... WHEN is where you go.
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 have got the MS SQL stored procedure, which is designed to return the results in XML showing all the applicants who are 'sales'.
There are filters on the page to drill down the results one being a search (sString).
The desired behavior is:
If sString is null, it should return all the results;
If sString is not null, it should make sString to the show the found fields.
The SP does not work as expected: it always returns all the results regardless of sString value.
MS SQL Code of the SP:
WITH OrderedMatches AS
(
SELECT ROW_NUMBER() OVER (ORDER BY MB.Member_Registered DESC) AS RowNumber,
MB.Member_ID,
MB.Member_Name, MB.Member_Mobile, MB.Member_Propertytosell, MB.Member_Propertytosell_Details, MB.Member_ExistingBuytoLet, MB.Member_TalkingPoints,
MB.Member_Registered, MB.Member_Funding, MB.Member_Active, MB.Member_Last_Contacted, MB.Member_Situation
FROM dbo.Member_Base MB INNER JOIN dbo.Member_Criteria MC ON MC.Member_ID = MB.Member_ID
WHERE MB.Member_Active = 1 AND MC.Criteria_Section = 'sales'
AND (
#sType = 'a'
OR (
#sType = 'b' AND MB.Member_Propertytosell = 1
)
OR (
#sType = 'c' AND MB.Member_ExistingBuytoLet = 1
)
)
OR (
MB.Member_Name LIKE '%' + #sString + '%' OR MB.Member_Mobile LIKE '%' + #sString + '%' OR MB.Member_Propertytosell_Details LIKE '%' + #sString + '%'
)
)
SELECT
(
SELECT
OM.Member_ID as "#id",
OM.Member_Name as "#appname",
OM.Member_Mobile as "#contact",
OM.Member_Propertytosell as "#propts",
OM.Member_Propertytosell_Details as "#proptsdetails",
OM.Member_ExistingBuytoLet as "#existingBTL",
OM.Member_TalkingPoints as "#talkingpoints",
OM.Member_Registered as "#registered",
OM.Member_Funding as "#funding",
OM.Member_Active as "#active",
OM.Member_Last_Contacted as "#lastcontact",
OM.Member_Situation as "#situation"
FROM OrderedMatches OM
WHERE OM.RowNumber Between #nstart AND #nend
FOR XML path ('applicant'), TYPE
),
(
SELECT COUNT(*) as "#titems"
FROM OrderedMatches
FOR XML path ('meta')
)
FOR XML PATH ('')
END
I suppose the SP is wrong but cant see at which part exactly.
Does anyone have any suggestions?
It's returning everything because you have OR between your sString condition and the rest of conditions in WHERE. Change your WHERE clause to:
WHERE MB.Member_Active = 1 AND MC.Criteria_Section = 'sales'
AND (
#sType = 'a'
OR (
#sType = 'b' AND MB.Member_Propertytosell = 1
)
OR (
#sType = 'c' AND MB.Member_ExistingBuytoLet = 1
)
)
AND (#sString IS NULL
OR
(
MB.Member_Name LIKE '%' + #sString + '%' OR MB.Member_Mobile LIKE '%' + #sString + '%' OR MB.Member_Propertytosell_Details LIKE '%' + #sString + '%'
)
)
I am using following SQL query to find difference between two datetime fields which is calculate night time shift,
For example
today work time is evening 190957 til next date morning 071152 so the between time in fab minute is 628, but out fab time will be calculate 798 min(Over calculate, more than IN fab time). so i want calculate in accurate minute.
SELECT
GROUP_SCANTIMECAL.EP_EMP_ID
,SUM(CAST(GROUP_SCANTIMECAL.INFAB_MIN AS FLOAT)) AS INFAB
,SUM(CAST(GROUP_SCANTIMECAL.OUTFAB_MIN AS FLOAT)) AS OUTFAB
FROM
(
SELECT SCANHIST.EP_SCAN_DATE
,SCANHIST.EP_EMP_ID
,SCANHIST.EP_EMP_NAME
,SCANHIST.EP_EMP_DEPT
,SCANHIST.EP_EMP_SECTION
,SCANHIST.EP_EMP_SHIFT
,SCANHIST.EP_TRANS_LOC
,DATEDIFF(MI,CAST(STUFF(STUFF(SCANHIST.EP_SCAN_DATE,12,0,':'),15,0,':') AS DATETIME),
CAST(STUFF(STUFF(NEXTSCAN.EP_SCAN_DATE,12,0,':'),15,0,':') AS DATETIME)) AS INFAB_MIN
,DATEDIFF(MI,CAST(STUFF(STUFF(NEXTSCAN.EP_SCAN_DATE,12,0,':'),15,0,':') AS DATETIME),
CAST(STUFF(STUFF(PREVSCAN.EP_SCAN_DATE,12,0,':'),15,0,':') AS DATETIME)) AS OUTFAB_MIN
FROM [AcmkIMS].[dbo].[EP_SCAN_HIST] SCANHIST
OUTER APPLY
(
SELECT TOP 1
NEXTSCAN.EP_SCAN_DATE
,NEXTSCAN.EP_EMP_ID
,NEXTSCAN.EP_EMP_NAME
,NEXTSCAN.EP_EMP_DEPT
,NEXTSCAN.EP_EMP_SECTION
,NEXTSCAN.EP_EMP_SHIFT
,NEXTSCAN.EP_SCAN_ID
,NEXTSCAN.EP_TRANS_DESC
,NEXTSCAN.EP_TRANS_LOC
FROM [AcmkIMS].[dbo].[EP_SCAN_HIST] NEXTSCAN
JOIN [AcmkIMS].[dbo].[EP_EMP_INFO] EMPINFO
ON EMPINFO.EP_EMP_ID = NEXTSCAN.EP_EMP_ID
JOIN [AcmkIMS].[dbo].[EP_SHIFT_CALENDAR] SHIFTCAL
ON SHIFTCAL.EP_SHIFT_NAME = NEXTSCAN.EP_EMP_SHIFT
AND SHIFTCAL.EP_SHIFT_DATE = LEFT(FIRSTSCAN.EP_SCAN_DATE,8)
JOIN [AcmkIMS].[dbo].[EP_SHIFT_DESC] SHIFTDESC
ON SHIFTDESC.EP_SHIFT_NAME = SHIFTCAL.EP_SHIFT
WHERE 1=1
AND SCANHIST.EP_SCAN_ID = NEXTSCAN.EP_SCAN_ID
AND NEXTSCAN.EP_SCAN_DATE > SCANHIST.EP_SCAN_DATE
AND NEXTSCAN.EP_SCAN_DATE < CASE WHEN (FIRSTSCAN.EP_SHIFT = 'N1')
THEN CONVERT(VARCHAR(8),DATEADD(DAY,+1,LEFT(NEXTSCAN.EP_SCAN_DATE,8)),112) + ' ' +
REPLACE(CONVERT(VARCHAR(8),DATEADD(HOUR,+6,SHIFTDESC.EP_SHIFT_TIMETO + ':00'),108),':','')
ELSE CASE WHEN (FIRSTSCAN.EP_SHIFT = 'R1' OR FIRSTSCAN.EP_SHIFT = 'R2')
THEN
LEFT(NEXTSCAN.EP_SCAN_DATE,8) + ' ' +
REPLACE(CONVERT(VARCHAR(8),DATEADD(HOUR,+0,SHIFTDESC.EP_SHIFT_TIMETO + ':00'),108),':','')
ELSE
LEFT(NEXTSCAN.EP_SCAN_DATE,8) + ' ' +
REPLACE(CONVERT(VARCHAR(8),DATEADD(HOUR,+6,SHIFTDESC.EP_SHIFT_TIMETO + ':00'),108),':','') END END
AND NEXTSCAN.EP_TRANS_LOC = 'OUT'
ORDER BY NEXTSCAN.EP_SCAN_DATE
)NEXTSCAN
OUTER APPLY
(
SELECT TOP 1
PREVSCAN.EP_SCAN_DATE
,PREVSCAN.EP_EMP_ID
,PREVSCAN.EP_EMP_NAME
,PREVSCAN.EP_EMP_DEPT
,PREVSCAN.EP_EMP_SECTION
,PREVSCAN.EP_EMP_SHIFT
,PREVSCAN.EP_SCAN_ID
,PREVSCAN.EP_TRANS_DESC
,PREVSCAN.EP_TRANS_LOC
FROM [AcmkIMS].[dbo].[EP_SCAN_HIST] PREVSCAN
JOIN [AcmkIMS].[dbo].[EP_EMP_INFO] EMPINFO
ON EMPINFO.EP_EMP_ID = PREVSCAN.EP_EMP_ID
JOIN [AcmkIMS].[dbo].[EP_SHIFT_CALENDAR] SHIFTCAL
ON SHIFTCAL.EP_SHIFT_NAME = PREVSCAN.EP_EMP_SHIFT
AND SHIFTCAL.EP_SHIFT_DATE = LEFT(FIRSTSCAN.EP_SCAN_DATE,8)
JOIN [AcmkIMS].[dbo].[EP_SHIFT_DESC] SHIFTDESC
ON SHIFTDESC.EP_SHIFT_NAME = SHIFTCAL.EP_SHIFT
WHERE 1=1
AND SCANHIST.EP_SCAN_ID = PREVSCAN.EP_SCAN_ID
AND PREVSCAN.EP_SCAN_DATE > SCANHIST.EP_SCAN_DATE
AND PREVSCAN.EP_SCAN_DATE < CASE WHEN (FIRSTSCAN.EP_SHIFT = 'N1')
THEN CONVERT(VARCHAR(8),DATEADD(DAY,+1,LEFT(SCANHIST.EP_SCAN_DATE,8)),112) + ' ' +
REPLACE(CONVERT(VARCHAR(8),DATEADD(HOUR,+6,SHIFTDESC.EP_SHIFT_TIMETO + ':00'),108),':','')
ELSE CASE WHEN (FIRSTSCAN.EP_SHIFT = 'R1' OR FIRSTSCAN.EP_SHIFT = 'R2')
THEN
LEFT(SCANHIST.EP_SCAN_DATE,8) + ' ' +
REPLACE(CONVERT(VARCHAR(8),DATEADD(HOUR,+0,SHIFTDESC.EP_SHIFT_TIMETO + ':00'),108),':','')
ELSE
LEFT(SCANHIST.EP_SCAN_DATE,8) + ' ' +
REPLACE(CONVERT(VARCHAR(8),DATEADD(HOUR,+6,SHIFTDESC.EP_SHIFT_TIMETO + ':00'),108),':','') END END
AND PREVSCAN.EP_TRANS_LOC = 'IN'
ORDER BY PREVSCAN.EP_SCAN_DATE
)PREVSCAN
JOIN [AcmkIMS].[dbo].[EP_EMP_INFO] EMPINFO
ON EMPINFO.EP_EMP_ID = SCANHIST.EP_EMP_ID
JOIN [AcmkIMS].[dbo].[EP_SHIFT_CALENDAR] SHIFTCAL
ON SHIFTCAL.EP_SHIFT_NAME = SCANHIST.EP_EMP_SHIFT
AND SHIFTCAL.EP_SHIFT_DATE = LEFT(FIRSTSCAN.EP_SCAN_DATE,8)
JOIN [AcmkIMS].[dbo].[EP_SHIFT_DESC] SHIFTDESC
ON SHIFTDESC.EP_SHIFT_NAME = SHIFTCAL.EP_SHIFT
WHERE 1=1
AND SCANHIST.EP_SCAN_DATE >= FIRSTSCAN.EP_SCAN_DATE
AND SCANHIST.EP_SCAN_DATE < CASE WHEN (FIRSTSCAN.EP_SHIFT = 'N1')
THEN CONVERT(VARCHAR(8),DATEADD(DAY,+1,LEFT(FIRSTSCAN.EP_SCAN_DATE,8)),112) + ' ' +
REPLACE(CONVERT(VARCHAR(8),DATEADD(HOUR,+6,SHIFTDESC.EP_SHIFT_TIMETO + ':00'),108),':','') ELSE
CASE WHEN (FIRSTSCAN.EP_SHIFT = 'R1' OR FIRSTSCAN.EP_SHIFT = 'R2')
THEN
LEFT(FIRSTSCAN.EP_SCAN_DATE,8) + ' ' +
REPLACE(CONVERT(VARCHAR(8),DATEADD(HOUR,+0,SHIFTDESC.EP_SHIFT_TIMETO + ':00'),108),':','')
ELSE
LEFT(FIRSTSCAN.EP_SCAN_DATE,8) + ' ' +
REPLACE(CONVERT(VARCHAR(8),DATEADD(HOUR,+6,SHIFTDESC.EP_SHIFT_TIMETO + ':00'),108),':','') END END
AND SCANHIST.EP_EMP_ID = FIRSTSCAN.EP_EMP_ID
AND SCANHIST.EP_TRANS_LOC = 'IN'
)GROUP_SCANTIMECAL
GROUP BY GROUP_SCANTIMECAL.EP_EMP_ID
)SCANTIMECAL
UPDATE PropertyInformationDump
SET RegistryAdd = COALESCE(NULLIF(b.OCAREOF, ''), b.OCAREOF + ', ','') +
COALESCE(NULLIF(b.O1STADD, ''), b.O1STADD + ', ','') +
COALESCE(NULLIF(b.O2NDADD, '') + b.O2NDADD + ', ','') +
COALESCE(b.OSTNAME + ', ','') + COALESCE(b.OCITYST + ' ','') +
COALESCE(NULLIF(b.OZIP, ''), b.OZIP,'')
FROM dbo.vw_BRT b
WHERE BRTNumber = b.PARCEL
GO
Looking to remove the commas that are in the front of these combined strings. Here is an example of what is happening:
, , 1350 SUSQUEHANNA AVE, PHILADELPHIA PA 19125
MICHAEL J CARLONE, 10050 ROOSEVELT BLVD, PHILADELPHIA PA 191163924
Need it to always look like:
1350 SUSQUEHANNA AVE, PHILADELPHIA PA 19125
or just how the one with the OCAREOF filled:
MICHAEL J CARLONE, 10050 ROOSEVELT BLVD, PHILADELPHIA PA 191163924
I need to get rid of those commas if the field is empty or null. Apparently I am doing this incorrectly!
using SQL Server 2005 the following should work
UPDATE PropertyInformationDump
SET RegistryAdd =
CASE WHEN Len(b.OCAREOF) > 0 THEN b.OCAREOF + ',' ELSE '' END +
CASE WHEN Len(b.O1STADD) > 0 THEN b.O1STADD + ',' ELSE '' END +
CASE WHEN Len(b.O2NDADD) > 0 THEN b.O2NDADD + ',' ELSE '' END +
CASE WHEN Len(b.OSTNAME ) > 0 THEN b.OSTNAME + ',' ELSE '' END +
CASE WHEN Len(b.OCITYST) > 0 THEN b.OCITYST+ ',' ELSE '' END +
CASE WHEN Len(b.OZIP) > 0 THEN b.OZIP+ ',' ELSE '' END
FROM dbo.vw_BRT b
WHERE BRTNumber = b.PARCEL
If the fields are either empty of have data then you can ignore using isNull()
Use this:
COALESCE(NULLIF(b.OCAREOF + ', ', ''),'')
UPDATE
If your fields are not nullable use this:
CASE WHEN LEN(b.OCAREOF) = 0 THEN '' ELSE b.OCAREOF + ', ' END +
....