SQL CASE in WHERE Incorrect Syntax - sql

Good Afternoon
Im programming in SQL and i have this problem
The Code is:
select
item.TX_Commercial_Family as 'Familia Comercial',
sum(nota.NM_Invoice_Quantity) as 'Quantidade Faturada' ,
sum(nota.NM_Material) as 'Valor Faturado'
from DW_DTS_Item item
INNER JOIN DIS_DTS_Invoice_Fact nota ON item.SK_Item = nota.SK_Item
inner join DW_DTS_Representative usuario on nota.SK_Representative=usuario.SK_Representative
inner join DW_DTS_Operation_Nature cfop on cfop.SK_Operation_Nature=nota.SK_Operation_Nature
where
item.CD_Inventory_Group='30'
and (
cfop.CD_CFOP='5101'
OR cfop.CD_CFOP='6101'
OR cfop.CD_CFOP='6107'
OR cfop.CD_CFOP='6108'
OR cfop.CD_CFOP='6109'
OR cfop.CD_CFOP='6113'
OR cfop.CD_CFOP='6401'
)
and(
case
when :number = '01' then nota.SK_Representative='05'
end
)
and nota.SK_Currency='1'
and nota.CD_Country='BRASIL'
and nota.DT_Sale_Forma_Bill_Exit between '2016-09-01' and '2016-09-30'
--and extract (year from nota.DT_Sale_Forma_Bill_Exit) = extract(year from CURRENT_DATE)
group by item.TX_Commercial_Family,usuario.TX_Representative,usuario.SK_Representative
order by usuario.TX_Representative asc
But when I compile the code, the following error appears
SQL Error [102][S0001]:Incorrect syntax near '='.
The point is that I have to pass a parameter and through this parameter filter through which SK_Representative will appear in the code.
I've tried everything but the error continues to appear

According to the error you are probably using SQL Server.
Replace :number with #number.
e.g.
declare #number int = 1;
select #number + 1;
set #number = #number * 10;
select #number;

As you want to use number as parameter then use '#' instead of ':'
So use the following snippet where u are using case statements.
and(
case
when #number = '01' then nota.SK_Representative='05'
end
)

Related

Multiple errors in SQL Server Function

I'm trying to make a function that evaluates the expiration date in a policy and based on that when is called in a Query it returns the text values ('Monthly'..and so on). but i'm getting a few errors of type "Incorrect syntax near Begin, declare expecting (.", "Must declare the scalar variable #policybillid" and in the end of the function "Incorrect syntax near ')'.". Any help would be appreciated.
USE [defaultDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE OR ALTER FUNCTION [dbo].[fn_Payment_GetPaymentCoutesByPaymentID]( #policybillid BIGINT, #companyID BIGINT) Returns TABLE
AS
RETURN (
BEGIN( ***Incorrect syntax near 'BEGIN'. Expecting '(', SELECT, or WITH.***
declare #expiresDates as table(expiredOn date) ***Incorrect syntax near 'declare'.*** Expecting '(', or SELECT.
insert into #expiresDates
select top(2) expiredOn from PolicyPaymentPlan
left join PolicyPaymentPlanFee on PolicyPaymentPlan.paymentPlanID= PolicyPaymentPlanFee.paymentPlanID
where PolicyPaymentPlan.policyBillID = #policybillid --Must declare the scalar variable "#policybillid".
order by cuoteID
select * from #expiresDates
declare #diffMonth int
declare #quota varchar(max) = ''
if((select count(*) from #expiresDates) > 1)
BEGIN
set #diffMonth = DATEDIFF(month, (select top(1) expiredOn from #expiresDates), (select top(1) expiredOn from #expiresDates order by expiredOn desc));
set #quota = ( SELECT
CASE
WHEN #diffMonth =1
then
'Monthly'
WHEN #diffMonth =2 THEN
'bimonthly'
WHEN #diffMonth =3 THEN
'trimonthly '
WHEN #diffMonth =4 THEN
'Four-Monthly'
WHEN #diffMonth =6 THEN
'biannual'
ELSE 'Cash'
END
)
END
) ***Incorrect syntax near ')'.***
There are numerous issues and syntax errors on your existing code. The main one is that an inline Table Valued Function can only have a single SELECT statement and nothing else.
So here is what it should look like.
CREATE OR ALTER FUNCTION [dbo].[fn_Payment_GetPaymentCoutesByPaymentID](
#policybillid BIGINT,
#companyID BIGINT
)
RETURNS TABLE
AS RETURN
SELECT Quota =
CASE WHEN COUNT(*) > 1 THEN
CASE DATEDIFF(month, MIN(expiredOn), MAX(expiredOn))
WHEN 1 THEN 'Monthly'
WHEN 2 THEN 'bimonthly'
WHEN 3 THEN 'trimonthly '
WHEN 4 THEN 'Four-Monthly'
WHEN 6 THEN 'biannual'
ELSE 'Cash'
END
END
FROM (
select top (2) expiredOn
from PolicyPaymentPlan pp
join PolicyPaymentPlanFee ppf on pp.paymentPlanID = ppf.paymentPlanID
where pp.policyBillID = #policybillid
order by cuoteID
) pp
;

Using scalar valued function in MSSM with data from 2 tables

I would like to here your advice on using a scalar valued function on MSSM that calculate average of data set coming 2 different table.
each table consist 12 columns that represent the values, in addition each table have 3 more columns to differ the data and when calculating the average these 3 columns should match (Product_ID, SalesRep_ID, and date (year)) on both tables
I Tried scalar valued function like this:
create FUNCTION [dbo].[Sales_BU_ScenarioB_PriceAv](#Product_ID nvarchar(255), #SalesRep_ID float, #Year float)
RETURNS decimal(18,0)
AS
BEGIN
DECLARE #Result decimal(18,0)
set #Result = (SELECT
case when
(
isnull(q.P01,0)
+ isnull(q.P02,0)
+ isnull(q.P03,0)
...
+ isnull(q.P12,0)
)
=0
then
0
else
(isnull(p.P01,0)*isnull(q.P01,0)
+ isnull(p.P02,0)*isnull(q.P02,0)
+ isnull(p.P03,0)*isnull(q.P03,0)
...
+ isnull(p.P12,0)*isnull(q.P12,0)
)
/
(
isnull(q.P01,0)
+ isnull(q.P02,0)
+ isnull(q.P03,0)
...
+ isnull(q.P12,0)
)
end
from DataEntrySalesQty$ q, DataEntrySalesPrice$ p
where #Year = p.Year and
#Product_ID = p.Product_ID and
#SalesRep_ID = p.SalesRep_ID)
RETURN #Result
END
this should calculate: sum((p.P01 * q.P01)....(p.P12 * q.P12)) and divide by: sum(q.P01,q.P02....q.P12) in order to get the average price for all relevant rows in these columns.
it looks like the function works when I run it, but when trying to test the result
select
Product_ID, SalesRep_ID, [Year], [dbo].[Sales_BU_ScenarioB_PriceAv](Product_ID, SalesRep_ID, [Year])
from DataEntrySalesQty$
I get the next error:
Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
can you please help me understand what i am doing wrong?
thanks for all the helpers
I would recommend cross apply to unpivot the columns to rows, then aggregation:
select
q.product_id,
q.year,
q.salesrep_id,
sum(x.p * x.q) / sum(x.q) avg_price
from DataEntrySalesPrice$ AS p
inner join DataEntrySalesQty$ AS q
on q.product_id = p.product_id
and q.year = p.year
and q.salesrep_id = p.salesrep_id
cross apply (values
(p.p01, q.q01),
(p.p02, q.q02),
...,
(p.p12, q.q12)
) as x(p, q)
group by q.product_id, q.year, q.salesrep_id

Adding dynamic condition in where clause

I want to add condition in 'where' clause depends upon 'if' condition like below
Declare #strSQLClause varchar(50)
If (#QMasterCompanyId='09' and #State='FL' and (#LOB='HO' or #LOB='HP'))
Begin
Declare #strMonthsOccupied char(1)
select Distinct #strMonthsOccupied=sm.MonthsOccupiedDesc from HOStructureRating sr
join HOSeleMonthsOccupied sm on sr.MonthsOccupied=sm.MonthsOccupiedCd
where AppId=#AppId
If(CONVERT(int,LTRIM(RTrim(#strMonthsOccupied))) > 9)
Begin
set #strSQLClause ='AND QuestionCd!=Q8'
End
Else
set #strSQLClause =''
End
so that in my Query will work as
select * from SHSeleQuestions where MasterCompanyId='09' + #strSQLClause
But this approach is not working fine, can anyone please help me on this.
There are two ways to do this one is use dynamic sql or other one is below mention :
select *
from SHSeleQuestions
where MasterCompanyId='09' AND
1 = CASE WHEN LEN(#strSQLClause) > 0 AND QuestionCd != 'Q8' THEN 1
WHEN LEN(#strSQLClause) = 0 THEN 1 END
Using Dynamic SQL
EXEC('select * from SHSeleQuestions where MasterCompanyId=''09''' + #strSQLClause ')
You would need to use dynamic SQL, but why not just have two statements that execute SQL, so rather than set #strSQLClause = 'AND ...', simply have a select statement here with the condition(s) you need
IF (#QMasterCompanyId='09' AND #State='FL' AND (#LOB='HO' OR #LOB='HP'))
BEGIN
DECLARE #strMonthsOccupied CHAR(1)
SELECT DISTINCT #strMonthsOccupied = sm.MonthsOccupiedDesc
FROM HOStructureRating sr
INNER JOIN HOSeleMonthsOccupied sm
ON sr.MonthsOccupied=sm.MonthsOccupiedCd
WHERE AppId=#AppId;
IF(CONVERT(INT,LTRIM(RTRIM(#strMonthsOccupied))) > 9)
BEGIN
SELECT *
FROM SHSeleQuestions
WHERE MasterCompanyId='09'
AND QuestionCd!='Q8';
RETURN;
END
END
SELECT *
FROM SHSeleQuestions
WHERE MasterCompanyId='09';
That being said, there are so many issues with the above I don't really know where to begin. You declare your variable then assign it an indeterminate value:
DECLARE #strMonthsOccupied CHAR(1)
SELECT DISTINCT #strMonthsOccupied = sm.MonthsOccupiedDesc
FROM HOStructureRating sr
INNER JOIN HOSeleMonthsOccupied sm
ON sr.MonthsOccupied=sm.MonthsOccupiedCd
WHERE AppId=#AppId;
If the query returns multiple rows then there is no clear logic for which value the variable should be assigned. The nex issue is that this CHAR(1) variable is clearly a number based on your attempted conversion:
IF(CONVERT(INT,LTRIM(RTRIM(#strMonthsOccupied))) > 9)
Why not just cut out the middle man and declare an INT to begin with. The next point is that it is a CHAR(1) so isn't actually big enough to store anything greater than 9, so your above condition will never be true.
Even if sm.MonthsOccupiedDesc, was 10, the variable would simply be truncated to 1, which is smaller than 9, so fails the condition, e.g.
DECLARE #strMonthsOccupied CHAR(1) = '10';
IF(CONVERT(INT,LTRIM(RTRIM(#strMonthsOccupied))) > 9)
PRINT 'TRUE';
ELSE
PRINT 'FALSE';

My closing parenthesis is throwing error

I am attempting to execute this query but I keep receiving error message
Msg 102, Level 15, State1
Incorrect syntax near ')'.
Would you please look over my query? I believe with every SQL keyword I've added the appropriate parenthesis.
USE [db]
GO
SET NOCOUNT ON
DECLARE #AlertDateTime date
, #HostName varchar(50)
, #Program varchar(100)
, #Event varchar(100)
, #Entity varchar(50)
, #Class tinyint
, #Severity tinyint
, #AlertMessage varchar(1024)
, #SkipFlag char(1)
select cast(getdate() as date)
IF EXISTS
(SELECT * FROM SendAlertLog
WHERE EXISTS
(
SELECT SendAlertLog.Event
FROM SendAlertLog
GROUP BY SendAlertLog.Event
HAVING COUNT (1) >= 2
)
AND SendAlertLog.SkipFlag != 'Y'
AND AlertDateTime <= DATEADD (mi,-30,#AlertDateTime)
)
I do not know what I am including or excluding wrong. Please help
Looks like you have an if, but no statement to do if the expression is true. You have
IF EXISTS(...)
But you need
IF EXISTS(...)
DO_SOMETHING
Try this one (without double usage of SendAlertLog) -
DECLARE #AlertDateTime DATE
IF EXISTS (
SELECT 1
FROM (
SELECT
cnt = COUNT(1)
, SkipFlag = MAX(l.SkipFlag)
, AlertDateTime = MAX(l.AlertDateTime)
FROM dbo.SendAlertLog l
GROUP BY l.[Event]
) l
WHERE cnt >= 2
AND l.SkipFlag != 'Y'
AND l.AlertDateTime <= DATEADD(mi, -30, #AlertDateTime)
) BEGIN
PRINT 'Do something'
END

SQL syntax issue using "IN" keyword with dynamic data

I am using SQL Server 2000 and having a wierd issue with a SQL code block (below):
A user can enter "GM" as a possible parameter or "F". If the user enters "GM" as a parameter in the stored proc query string, I need the AutoDivision to include GMC, CAD, CHE,SAT
declare #AutoDivision as varchar(15)
set #AutoDivision = 'GM'
if #AutoDivision = 'GM'
Begin
Select #AutoDivision = '''Cad'', ''GMC'', ''Sat'', ''Che'''
End
SELECT
oh.OrderNumber, lg.[lgh_number]
FROM
[dbo].[OrderHeader] oh (NOLOCK)
INNER JOIN
[dbo].[DistrctHeader] lg (NOLOCK) ON oh.[inv_number] = lg.[inv_number]
INNER JOIN
[dbo].[DealerCompany] c (NOLOCK) ON c.cmp_id = LEFT(oh.[ordernumber],3)
INNER JOIN
[dbo].[divisionXREF] x (NOLOCK) ON x.Division = c.comp_revtype
WHERE
oh.ord_number = '113-889257'
AND x.AutoDivision IN (#AutoDivision)
--AND x.AutoDivision IN ('Cad', 'Sat', 'GMC', 'Che')
AND lg.[lgh_outstatus] IN ('AVAIL', 'PLAN', 'DISP', 'STRTD', 'PEND','COMP')
However, when I run the code below, I don't get back any records.
When I uncomment the code line
--AND x.AutoDivision IN ('Cad', 'Sat', 'GMC', 'Che')
it works (I get a record returned).
When I do a print 'AND x.AutoDivision IN (' + cast(#AutoDivision as varchar) + ')'
I get back AND x.AutoDivision IN ('Cad', 'GMC', 'Sat', 'Che')
What am I missing here?
You can't use a single variable to represent a comma separated list of IN parameters in SQL - Oracle, MySQL, SQL Server... doesn't matter.
To get this variable method to work, you need to use dynamic SQL so you are able to create the query as a string first (using concatenation to get the IN parameters from your variable), and the query statement is executed afterwards:
DECLARE #cmd VARCHAR(1000)
SET #cmd = 'SELECT oh.OrderNumber,
lg.[lgh_number]
FROM [dbo].[OrderHeader] oh (NOLOCK)
JOIN [dbo].[DistrctHeader] lg (NOLOCK) ON oh.[inv_number] = lg.[inv_number]
JOIN [dbo].[DealerCompany] c (NOLOCK) ON c.cmp_id = LEFT(oh.[ordernumber],3)
JOIN [dbo].[divisionXREF] x (NOLOCK) ON x.Division = c.comp_revtype
WHERE oh.ord_number = '113-889257'
AND x.AutoDivision IN ('+ #AutoDivision +')
AND lg.[lgh_outstatus] IN (''AVL'', ''PLN'', ''DSP'', ''STD'', ''PND'',''CMP'') '
EXEC(#cmd)
I recommend reading The Curse and Blessings of Dynamic SQL before implementing a dynamic SQL solution.
Table Valued Function
A table valued function would allow you do what you want without using dynamic SQL -- there's more info in this article.
To avoid this, you can create a temp table, fill it in, then use
IN (SELECT myField from #myTable)
Even though you concatenate what looks like a few different arguments your IN clause is actually testing it as a single string (you did declare it as a varchar) and it's no surprise that no records match that predicate.
Looks like you're trying to mix dynamic sql and a standard query. That won't work. Your query either has to be all dynamically created and then specially executed or your IN clause has to be inputed with individual arguments which can be done by subqery.
You could do something like:
... AND x.AutoDivision IN
(SELECT Division WHERE Corp = 'GM') ...
OR
... AND x.AutoDivision IN
(SELECT 'Cad' UNION SELECT 'GMC' UNION SELECT 'Sat' UNION SELECT 'Che') ...
Try this:
SELECT
oh.OrderNumber, lg.[lgh_number]
FROM
[dbo].[OrderHeader] oh (NOLOCK)
INNER JOIN
[dbo].[DistrctHeader] lg (NOLOCK) ON oh.[inv_number] = lg.[inv_number]
INNER JOIN
[dbo].[DealerCompany] c (NOLOCK) ON c.cmp_id = LEFT(oh.[ordernumber],3)
INNER JOIN
[dbo].[divisionXREF] x (NOLOCK) ON x.Division = c.comp_revtype
WHERE
oh.ord_number = '113-889257'
AND x.AutoDivision IN
(SELECT 'Cad' UNION SELECT 'GMC' UNION SELECT 'Sat' UNION SELECT 'Che')
AND lg.[lgh_outstatus] IN ('AVL', 'PLN', 'DSP', 'STD', 'PND','CMP')
That is an inline subquery that UNIONs arbitrary strings into a result set. (Take with a grain of salt. I am a long way from a Sql Server interface.)
AND x.AutoDivision IN (#AutoDivision)
--AND x.AutoDivision IN ('Cad', 'Sat', 'GMC', 'Che')
Can you clarify these two lines of code, are they not doing the same thing?
CREATE FUNCTION [dbo].[Split]
(
#String NVARCHAR(4000),
#Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
GO
DECLARE #AutoDivision varchar(50) = NULL
SET #AutoDivision ='Cad, Sat, GMC, Che'
SELECT * FROM divisionXREF P INNER JOIN dbo.SPLIT(ISNULL(#AutoDivision,''),',') as T ON P.lgh_outstatus = CASE T.strval WHEN '' THEN P.PG_CODE ELSE T.strval END