Using CASE expression inside a where clause - sql

I have a stored proc with 2 parameters, both integer
I need to use case statement inside where clause but i could not get it right
where
dbo.StockTransfer.BranchId = #branchId
AND
CASE WHEN IsNumeric(#roleId) = 1
THEN
dbo.StockTransfer.StatusId !=12
ELSE
dbo.StockTransfer.StatusId NOT in (12, 13)
END
order by dbo.StockTransfer.StatusId ASC
I am getting an error in 'dbo.StockTransfer.StatusId !=12'
Msg 102, Level 15, State 1, Procedure GetDeliveryList, Line 44 [Batch Start Line 0]
Incorrect syntax near '!'.

Don't bother. Just use regular logic:
where dbo.StockTransfer.BranchId = #branchId and
( (IsNumeric(#roleId) = 1 and
dbo.StockTransfer.StatusId <> 12
) or
(IsNumeric(#roleId) = 0 and
dbo.StockTransfer.StatusId not in (12, 13)
)
)
This doesn't handle NULL values, but that can easily be added.
Actually, I might simplify this to:
where dbo.StockTransfer.BranchId = #branchId and
dbo.StockTransfer.StatusId <> 12 and
(IsNumeric(#roleId) = 1 or
dbo.StockTransfer.StatusId <> 13
)

Given the newest comments about what you want to return I think it would be something like this. I added lots of white space for clarity on the parenthesis.
where dbo.StockTransfer.BranchId = #branchId
AND
(
(
#roleId = 1
AND
StatusId in (13, 14)
)
OR
(
#roleId <> 1
AND
StatusId = 14
)
)

Related

SQL MERGE error? [duplicate]

This question already has an answer here:
Msg 8672, Level 16, State 1, Line 1 The MERGE statement attempted to UPDATE or DELETE the same row more than once
(1 answer)
Closed 4 years ago.
Please see my below code - I am new to SQL and haven't seen this error before. Can someone advise as to where it is going wrong? The error I am getting is
(41669 row(s) affected) Msg 8672, Level 16, State 1, Line 41 The MERGE
statement attempted to UPDATE or DELETE the same row more than once.
This happens when a target row matches more than one source row. A
MERGE statement cannot UPDATE/DELETE the same row of the target table
multiple times. Refine the ON clause to ensure a target row matches at
most one source row, or use the GROUP BY clause to group the source
rows.
My code is below
DECLARE #FromDate DateTime = '31 jan 2018'
DECLARE #ToDate DateTime = '28 Feb 2018'
DECLARE #FromDate_In DateTime = #FromDate
DECLARE #ToDate_In DateTime = #ToDate
DECLARE #DirectDebit_In INT = 0
/**************************/
/* Agreement view */
/**************************/
SELECT
sag.[AgreementID]
,sca.CustomerID
,'Lost' AS [Type]
INTO #AgreementSet
FROM Money.dbo.[Fin_SS_TblAgreements] sag WITH (NOLOCK)
INNER JOIN Money.dbo.[Fin_SS_TblCustomersAgreements] [sca] WITH (NOLOCK) ON sca.DealID = sag.DealID AND sca.IsMasterCustomer = 1 AND sca.[SnapShot] = sag.[SnapShot]
INNER JOIN (
SELECT
sps.DealID
FROM Money.dbo.[Fin_SS_TblPaymentSchedule] sps WITH (NOLOCK, INDEX(IX_NC_Snapshot))
WHERE sps.[SnapShot] = #FromDate_In
GROUP BY sps.DealID
) sps ON sag.DealID = sps.DealID
WHERE sag.[SnapShot] = #FromDate_In
AND (sag.AgreementID IS NOT NULL)
AND ((sag.EndDate > sag.[SnapShot]) OR (sag.EndDate = sag.[SnapShot] AND sag.Autorenew = 1))
AND (sag.AgreementStartsOn <= sag.[SnapShot])
AND ( (#DirectDebit_In = 0 AND sag.ContractTypeID <> 3) OR (#DirectDebit_In = 1 AND sag.ContractTypeID = 3) OR (#DirectDebit_In = 3) )
DECLARE #MaxAgIDFrom INT
SELECT #MaxAgIDFrom = MAX(AgreementID) FROM Money.dbo.[Fin_SS_TblAgreements] WHERE [SnapShot] = #FromDate_In
DECLARE #MaxCIDFrom INT
SELECT #MaxCIDFrom = MAX(CustomerID) FROM #AgreementSet
MERGE INTO #AgreementSet L
USING (
SELECT
sag.[AgreementID]
,sca.CustomerID
,'New' AS [Type]
FROM Money.dbo.[Fin_SS_TblAgreements] sag WITH (NOLOCK)
INNER JOIN Money.dbo.[Fin_SS_TblCustomersAgreements] [sca] WITH (NOLOCK) ON sca.DealID = sag.DealID AND sca.IsMasterCustomer = 1 AND sca.[SnapShot] = sag.[SnapShot]
INNER JOIN (
SELECT
sps.DealID
FROM Money.dbo.[Fin_SS_TblPaymentSchedule] sps WITH (NOLOCK, INDEX(IX_NC_Snapshot))
WHERE sps.[SnapShot] = #ToDate_In
GROUP BY sps.DealID
) sps ON sag.DealID = sps.DealID
WHERE sag.[SnapShot] = #ToDate_In
AND (sag.AgreementID IS NOT NULL)
AND ((sag.EndDate > sag.[SnapShot]) OR (sag.EndDate = sag.[SnapShot] AND sag.Autorenew = 1))
AND (sag.AgreementStartsOn <= sag.[SnapShot])
AND ( (#DirectDebit_In = 0 AND sag.ContractTypeID <> 3) OR (#DirectDebit_In = 1 AND sag.ContractTypeID = 3) OR (#DirectDebit_In = 3) )
) N
ON L.AgreementID = N.AgreementID
WHEN MATCHED THEN
UPDATE SET [Type] =
CASE WHEN L.CustomerID = n.CustomerID THEN 'B/F'
ELSE 'Swap'
END
WHEN NOT MATCHED THEN
INSERT (AgreementID, CustomerID, [Type])
VALUES (n.AgreementID, n.CustomerID, n.[Type])
We get this very often.
This happens because of unique column that is being used in more than one row.
In your case this may be because of same agreementid for two or more different customers.
Check the data again and perform the same operation again.

Complex switch Case SQL

I am stuck in a complex SQL switch case statement in the midst of a stored procedure.
I am copying the middle part of the stored procedure:
AND
(
#Statuses IS NULL
OR
[BF].[BookingFileStatusID] IN
(
SELECT [ID]
FROM #BookingFileStatuses)
AND
(
#Statuses IS NULL
OR
**((
(
SELECT count([ID])
FROM #BookingFileStatuses) >= 1)
AND
(
1 = (
CASE
WHEN [S].servicetypeid IS NULL THEN 1
WHEN (
[S].servicetypeid <> 3
AND
[BF].bookingfilestatusid IN ( 16, 17, 18, 19, 20, 23)
)
THEN 1
WHEN (
[S].servicetypeid = 3
AND
[BF].bookingfilestatusid IN
(
SELECT [ID]
FROM #BookingStatuses)
)
THEN 1
ELSE 0
END)
)
)**
)
)
Highlighted portion should return some results.
i.e. replace the highlighted portion with if else.
Please assist.
You could rewrite the whole thing without the case statement. It is easier to read this way.
(
(SELECT Count([ID]) FROM #BookingFileStatuses) >= 1
AND
( [S].ServiceTypeID IS NULL
OR ([S].ServiceTypeID <> 3 AND [BF].BookingFileStatusID in (16,17,18,19,20,23))
OR ([S].ServiceTypeID = 3 AND [BF].BookingFileStatusID in (SELECT [ID] FROM #BookingStatuses))
)
)
In this part :
AND ( #Statuses IS NULL
OR
1 = (CASE WHEN #BookingStatusCount = 0 THEN 1
ELSE
xxxxxxxxxxxxxxxx
END)
)
you are making Or with two cases : 1=( 1 or sth else). so you don't need the second query at all. because alway you can make one value. I would like to write this:
AND ( #Statuses IS NULL
OR
1 = (CASE WHEN #BookingStatusCount = 0 THEN 1 else 5)
)

SQL Server : table-valued function does not work with sub query

I have a SQL Server table-valued function which is created by me I have pasted the create script below
CREATE FUNCTION [dbo].[getTableFromString]
(
#String AS nvarchar(max)
)
RETURNS #ReturnTable TABLE ( StringValues nvarchar(10) )
AS begin
if (SELECT CHARINDEX(',', #String)) = 0
begin
insert into #ReturnTable (StringValues) values (subString(#String,1,len(#String)));
end
else
begin
while (SELECT CHARINDEX(',', #String)) > 0
begin
insert into #ReturnTable (StringValues) values (subString(#String,1,CHARINDEX(',', #String)-1));
set #String = subString(#String,CHARINDEX(',', #String)+1,len(#String));
if (SELECT CHARINDEX(',', #String)) = 0
begin
insert into #ReturnTable (StringValues) values (subString(#String,1,len(#String)));
end
end
end
return ;
end
and I am using this function like below
Select sum(NetSales)
from vwxsalesall
where Company = 'rs'
and storecode = (select cPrimaryStockRoomCode from CompanyMaster.CompanyProfileDetail where cCompanyNo = 'rs' and cSecondaryStockRoomCode = 'R01B')
and trandate >= '2012-01-01'
and trandate <= '2012-01-31'
and (
brand in (
select StringValues from dbo.getTableFromString(
select vIncludedBrandCodes
from StockRoomTargetData.MonthlyTarget
where cCompanyNo = 'rs'
and cSecondaryStockRoomCode = 'R01B'
and nYear = 2012
and nMonth = 8
)
)
)
Unfortunately I am getting this error
Msg 156, Level 15, State 1, Line 10
Incorrect syntax near the keyword 'select'.
Msg 102, Level 15, State 1, Line 16
Incorrect syntax near ')'.
please help me
You need to add another set of parenthesis around subquery, for instance
select StringValues from dbo.getTableFromString(( { your-subquery }))
^ ^
(parenthesis added)
First set of parenthessis syntactically belong to TVF invocation, and second denote a subquery.
And now your query:
Select sum(NetSales)
from vwxsalesall
where Company = 'rs'
and storecode = (select cPrimaryStockRoomCode from CompanyMaster.CompanyProfileDetail where cCompanyNo = 'rs' and cSecondaryStockRoomCode = 'R01B')
and trandate >= '2012-01-01'
and trandate <= '2012-01-31'
and (
brand in (
select StringValues from dbo.getTableFromString((
select vIncludedBrandCodes
from StockRoomTargetData.MonthlyTarget
where cCompanyNo = 'rs'
and cSecondaryStockRoomCode = 'R01B'
and nYear = 2012
and nMonth = 8
))
)
)

Using CASE Statement inside IN Clause

Is is possible to use a CASE statement inside an IN clause?
This is a simplified version of what I have been trying to get to compile correctly:
SELECT * FROM MyTable
WHERE StatusID IN (
CASE WHEN #StatusID = 99 THEN (5, 11, 13)
ELSE (#StatusID) END )
Thanks!
CASE returns a scalar value only. You can do this instead. (I am assuming, as per your example, that when #StatusID = 99, a StatusID value of 99 is not a match.)
select *
from MyTable
where (#StatusID = 99 and StatusID in (5, 11, 13))
or (#StatusID <> 99 and StatusID = #StatusID)
No. Instead, you can put it outside
SELECT *
FROM MyTable
WHERE 1 = (CASE WHEN #StatusID = 99 and StatusId in (5, 11, 13) then 1
WHEN coalesce(#StatusId, 0) <> 99 and StatusId in (#StatusID) then 1
ELSE 0
END)
You can also write this without the case statement.
Another option is dynamic SQL, where you actually create a string with the SQL statement and then execute it. However, dynamic SQL seems like overkill in this case.
I thought I'd attempt this differently using a Table Valuue Constructor - are TVCs not allowed in the following context?
SELECT *
FROM MyTable
WHERE StatusID IN
(
SELECT
CASE
WHEN #StatusID = 99 THEN (values(5),(11),(13)) t(StatusID )
ELSE #StatusID
END
)
You can do this using TVCs, but the approach is a little different. It doesn't use case, but it will scale more nicely where there are a number of possible options to choose from:
SELECT *
FROM MyTable
join (values
(99,5),(99,11),(99,13),
(#StatusID , #StatusID)
) t(k,v) on t.k= #StatusID and t.v = StatusID)
or if you need everything in the where clause then:
SELECT *
FROM MyTable
WHERE exists (
select 1
from (values
(99,5),(99,11),(99,13),
(#StatusID , #StatusID)
) t(k,v)
where t.k= #StatusID and t.v = StatusID)

if statement in sql server

i am getting the following error:
Incorrect syntax near 'cast', expected 'AS'.
on this line:
use SalesDWH
go
if (select isnumeric(result))=1
begin
select max(cast(result) as decimal(10,2)) from testresults
end
testresults table contains about 21 million rows of data.
what am i doing wrong? thanks so much.
thank you everyone for you rhelp.
i've changed the code to:
use SalesDWH
go
if (select isnumeric(result))=1
begin
select max(cast(result as decimal(10,2))) from testresults
end
and now i am getting error:
Msg 207, Level 16, State 1, Line 1
Invalid column name 'result'.
it's definitely a valid column
i took kris' suggestion and did this:
use SalesDWH
go
SELECT MAX( CAST( [Result] AS DECIMAL(9,2) ) )
FROM [testresults]
WHERE ISNUMERIC( [Result] ) = 1
and dbo.isReallyNumeric([Result]) = 1
and dbo.isReallyInteger([Result]) = 1
the functions are here http://classicasp.aspfaq.com/general/what-is-wrong-with-isnumeric.html
and the result that i got was NULL!!!!!
i need a numeric result. what am i doing wrong?
here is a sample of the data:
625857 AMPH-AMPHETAMINES 357.1 EBB74CF9-D12D-4FBC-917F-91D9DAC169F3
625858 AMP_C-Amphetamine NEGATIVE EBB74CF9-D12D-4FBC-917F-91D9DAC169F3
625859 BARB-BARBITURATES 7.1 EBB74CF9-D12D-4FBC-917F-91D9DAC169F3
625860 BENZ-BENZODIAZEPINES 1.2 EBB74CF9-D12D-4FBC-917F-91D9DAC169F3
625861 COCN-COCAINE METABOLITES -105.5 EBB74CF9-D12D-4FBC-917F-91D9DAC169F3
625862 CR-CREATININE (CHEMICAL) 57.8 EBB74CF9-D12D-4FBC-917F-91D9DAC169F3
625863 ETOH-ETHANOL 134.5 EBB74CF9-D12D-4FBC-917F-91D9DAC169F3
625864 METAMP_C-Methamphetamine NEGATIVE EBB74CF9-D12D-4FBC-917F-91D9DAC169F3
625865 METD-METHADONE -32.3 EBB74CF9-D12D-4FBC-917F-91D9DAC169F3
thank you for all your help. i think i am getting closer:
select MAX(cast(char_value as decimal(10,2))) from
(SELECT
Char_Number = CASE
WHEN id <= 255 THEN RTRIM(id)
ELSE '-' END,
Char_Value = RTRIM(CASE
WHEN id <= 255 THEN CHAR(id)
ELSE result END),
is_numeric = ISNUMERIC(result),
is_really_numeric = dbo.isReallyNumeric(result),
is_really_integer = dbo.isReallyInteger(result)
FROM
testresults
WHERE
ISNUMERIC(result) = 1
OR dbo.isReallyNumeric(result) = 1
OR dbo.isReallyInteger(result) = 1
)
where is_really_numeric=1
but i am getting this error:
Msg 156, Level 15, State 1, Line 20
Incorrect syntax near the keyword 'where'.
updated based on guess of what you were looking for
SELECT MAX( CAST( [Result] AS DECIMAL(10,2) ) )
FROM [testresults]
WHERE ISNUMERIC( [Result] ) = 1;
Try this one
use SalesDWH
go
SELECT MAX(CAST(Result AS DECIMAL(10,2))) FROM testresults WHERE isnumeric(result)=1
But if you get NULL as a result even with this:
and dbo.isReallyNumeric([Result]) = 1
and dbo.isReallyInteger([Result]) = 1
then this may be the actual result - there is no any numberic values in the column
OR
the really numberic values of column are left- or right-padded with spaces etc...
OR
you stripe all the floats with this dbo.isReallyInteger([Result]) = 1 and you have no pure integers in the table
If you are still getting the error, just give an alias to your inner table.
select MAX(cast(char_value as decimal(10,2))) from
(SELECT
Char_Number = CASE
WHEN id <= 255 THEN RTRIM(id)
ELSE '-' END,
Char_Value = RTRIM(CASE
WHEN id <= 255 THEN CHAR(id)
ELSE result END),
is_numeric = ISNUMERIC(result),
is_really_numeric = dbo.isReallyNumeric(result),
is_really_integer = dbo.isReallyInteger(result)
FROM
testresults
WHERE
ISNUMERIC(result) = 1
OR dbo.isReallyNumeric(result) = 1
OR dbo.isReallyInteger(result) = 1
) myInnerTable
where is_really_numeric=1