MS SQL Server tells me 'expecting EOS' under the conditional statement starting from CASE.
Can somebody figure out what is wrong with this code?
SELECT
goal,
AVG(pledged) AS avg_num_pledged,
AVG(backers) AS avg_num_backers
CASE WHEN currency='GBP' THEN goal*1.3
ELSEIF =currency ='CAD' THEN goal*0.76
ELSEIF currency ='AUD' THEN goal*0.71
ELSEIF currency ='NOK' THEN goal*0.11
ELSEIF currency ='EUR' THEN goal*1.18
ELSEIF currency ='MXN' THEN goal*0.048
ELSEIF currency='SEK' THEN goal*0.11
ELSEIF currency='NZD' THEN goal*0.67
ELSEIF currency='CHF' THEN goal*1.11
ELSEIF currency='DKK' THEN goal*0.16
ELSEIF currency='HKD' THEN goal*0.13
ELSEIF currency='SGD' THEN goal*0.74
ELSEIF currency='JPY' THEN goal*0.0095
ELSE goal
END AS currency_uniformed
FROM kickstarter;
As indicated in the comments earlier, the CASE syntax is incorrect. You can also move the multiplication outside the CASE expression. To get a runnable query there is also a grouping clause missing to handle the aggregation (AVG()) across the goal column.
SELECT goal,
AVG(
case currency
when 'GBP' then 1.3
when 'CAD' then 0.76
when 'AUD' then 0.71
...
else 1
end * goal) AS goal_currency_uniformed,
AVG(pledged) AS avg_num_pledged,
AVG(backers) AS avg_num_backers
FROM kickstarter
GROUP BY goal;
Please consider moving the exchange rates to a separate table. This will allow you to slim this query down a bit and has the additional advantage that you can update the exchange rates without reworking your code.
SELECT ks.goal,
AVG(er.rate * ks.goal) as goal_currency_uniformed,
AVG(pledged) AS avg_num_pledged,
AVG(backers) AS avg_num_backers
FROM kickstarter ks
JOIN exchangerates er ON er.currency = ks.currency
GROUP BY goal;
Fiddle to see everything in action.
Related
I try running the below code and I get an error saying
Unexpected CASE
I am not sure what's wrong with the code. My original table already has 5 columns. It has the Customer id, first name, last name, debt, and accountstatus. I have a blank column called "accountstatus" which I need to fill in using a case statement.
INSERT INTO customeraccounts (accountstatus)
CASE
WHEN debt = 0 THEN "closed"
WHEN debt > 0 THEN "open"
WHEN debt < 0 THEN "refund needed"
END
To fill the accountstatus using case statement You can do it as follows :
Update customeraccounts
set accountstatus = CASE
When debt = 0 then "closed"
When debt > 0 then "open"
When debt < 0 then "refund needed"
END
Hello I am missing something because my code errors.
select * from ##ScheduleDetail SD
left join ##HolidayFilterTbl HF on SD.Scheduledate = HF.Testdate
where (ScheduleDate = testdate)
and
(Case
when HF.IsHoliday = 1 then (overtime = 1 and makeup = 0)
else
(overtime = 0 and Makeup = 0)
end
)
and
DOW = 5
order by ActivityStartTime
I've attempted several combinations and each one errors at either the first equal sign or the second. What am I missing?
The branches of a case expression can only return values, not additional expressions to be evaluated in the where condition. You could, however, simulate this behavior with the and and or logical operators:
select *
from ##ScheduleDetail SD
left join ##HolidayFilterTbl HF on SD.Scheduledate = HF.Testdate
where (ScheduleDate = testdate) and
((HF.IsHoliday = 1 and overtime = 1 and makeup = 0) or
(overtime = 0 and Makeup = 0)) and
DOW = 5
order by ActivityStartTime
Note that you have makeup = 0 on both branches of the case expression in the question (or both sides of the or in the answer), so you could extract it out of it and simplify the condition a bit:
select *
from ##ScheduleDetail SD
left join ##HolidayFilterTbl HF on SD.Scheduledate = HF.Testdate
where ScheduleDate = testdate and
makeup = 0 and
((HF.IsHoliday = 1 and overtime = 1) or
overtime = 0) and
DOW = 5
order by ActivityStartTime
If you are still wanting to know how to utilize a CASE Statement Expression in a WHERE Clause the CASE Expression must be compared to a value as that is the syntax understood for conditions contained within a WHERE Clause. See below a mock example.
SELECT *
FROM ##ScheduleDetail SD
LEFT JOIN ##HolidayFilterTbl HF ON SD.Scheduledate = HF.Testdate
WHERE(ScheduleDate = testdate)
AND
/* If you wish to stick with using a CASE Expression within the WHERE Clause set the the CASE Expression equal to 'something'. I usually stick with 1 or 0 'true/false'.
| You simply have to create your own True/False evaluation. You can add your logic checks within a CASE Expression within
| the WHERE Clause and when your logic is TRUE THEN return 1. Basically you are saying when 1 = 1 then return Record.
*/
1 =
Case
WHEN HF.IsHoliday = 1 AND makeup = 0 THEN
CASE WHEN (overtime = 1 OR overtime = 0) THEN 1 END /* Return 1 here to evaluation to TRUE */
ELSE
0 /* You can add another CASE here if needed and when the condition you write in evaluations to 1 'true' return record */
END
AND
DOW = 5
ORDER BY ActivityStartTime;
There are a few reasons I've used CASE Expressions within a WHERE Clause over using AND/ORs. Just one minor reason is it allows me to contain and organize logic in a WHERE Clause inside CASE Expressions rather than having multiple AND/ORs all nested together. I've also found that using CASE Expressions in the WHERE Clause is useful when encountering Dynamic queries that accept variables to be later inserted into the SQL before being sent to the database for processing. In the case of using Dynamic SQL there are times when a CASE Statement MUST be used due to the fact that there could be data that is being compared against in the WHERE clause that is NOT a column.field value but a hardcoded value that is compared to perhaps a user selection or status (as examples)... it might be a static value passed in via the application which is how my web application works that I support which is why I bring it up.
Basically it's good to know how to use a CASE Expression in a WHERE Clause as there are some cases when the ONLY way to evaluate certain data is by using a CASE Expression .
I have no data to test this against and that's not the point. The point of my answer is to simply provide to you an alternative to the existing answer. In my opinion this logic is basic and the already provided answer is the correct one however my answer is to demonstrate how you could go about using a CASE in a WHERE Clause.
If interested see this SO Post for the differences between a CASE Statement vs a CASE Expression however know that this terminology slightly differs between databases.
As an example of this... SQL Server refers to these as Simple vs Searched but refers to all of it as a CASE Expression. Therefore a CASE Expression can either be a Simple or a Searched CASE that can be used within a Statement.
I have two CTEs using the same table which holds receipts. Receipt type "a" says how much is billed and may or may not have an amount received. Receipt type "b"s have how much was received if it was received outside of the original receipt. These are matched up by mnth, cusnbr and job. Also on the receipt is how much is allocated for different expenses on the receipt.
I am trying to total up peoples hours if the receipt has been paid at least 99%. These records are based on cusnbr, jobnbr and mnth also. The code below works fine.
with billed as(Select cusnbr
,job
,mnth
,sum(bill_item_1) as 'Billed Item'
,sum(billed) as 'Billed'
From accounting
Where mytype in ('a','b')
Group by cusnbr
,job
,mnth)
paid as(Select cusnbr
,job
,mnth
,sum(rcpt_item_1) as 'Rcpt Item'
,sum(billed) as 'Paid'
From accounting
Where mytype in ('a','b')
Group by cusnbr
,job
,mnth)
Select b.cusnbr
,b.job
,b.mnth
,sum(g.hours) as 'Total Hours'
,b.[Billed Item]
,p.[Rcpt Item]
From billed b inner join paid p
on b.cusnbr = p.cusnbr
and b.job = p.job
and b.mnth = p.mnth
inner join guys g
on b.cusnbr = g.cusnbr
and b.job = g.job
and b.mnth = g.mnth
Where p.[Paid]/b.Billed > .99
The issue I'm having is if I try to add
and b.[Billed Item] <> 0
To the where clause.
I get "Divide by zero error encountered"
I have tried making the last query a CTE with
case when b.[Billed Item] = 0 then 1 else 0 end as flag
and then making another query which checks that flag <> 0
I have tried using isnull(b.[Billed Item],0) in the last query as well as isnull(bill_item_1,0) in the first CTE.
I can get around this issue by dumping the whole thing into a temp table and querying that, but just want to know why this is happening. Using ">","<" or "<>" against b.[Billed Item] results in a divide by zero error.
Use nullif():
Where p.[Paid] / nullif(b.Billed, 0) > 0.99
This will return null -- which does not meet the condition. You can also phrase this more simply without division as:
where p.paid > b.billed * 0.99
I can't answer you question specifically, but I can tell you that SQL does not process all commands if it does not need to. For example,
SELECT COUNT(1/0)
Happily returns 1. So it is quite possible the order of the conditions cause the optimizer to filter out an uncessary division by zero condition.
I have been doing this
SELECT
movi.Usuario AS RowUsuario, movi.MovID, MIN(Art.Descripcion1),
MIN(com.ReferenciaExtra), MIN(com.Unidad), MIN(Art.UnidadCompra),
MIN(movi.FechaEmision),
error = CASE
WHEN MIN (com.Unidad) NOT LIKE
CASE
WHEN MIN (ar.Unidad) LIKE com.Unidad THEN art.Unidad
END
THEN 1
ELSE 0
END
FROM
CompraD com
INNER JOIN
Mov movi ON com.ID = movi.ID
INNER JOIN
Art ON com.Articulo = Art.Articulo
WHERE
movi.Mov = 'Requisicion
ORDER BY
movi.FechaEmision ASC
`when 'com.unidad' dont match with art.Unidad, add 1 or 0 if they match
SQL Server says:
incorrect syntax CASE
The incorrect syntax error is referring to the
error = CASE part.
It should be
CASE statement END AS error
However I'm not sure if that will solve your problem as the case statements looks a little odd to me but get that bit the right way around and then let us know of any further error messages.
Possibly...
SUM(CASE WHEN com.Unidad <> ar.Unidad THEN 1 ELSE 0 END AS error)
Also, you are missing a GROUP BY clause, if you want to use aggregate functions (MIN for example) you need to GROUP BY the non aggregate fields.
You have WHEN MIN (ar.Unidad) LIKE com.Unidad THEN art.Unidad but I do not see ar aliased anywhere.
Also you need to either have GROUP BY or OVER clause with your MINs.
If you want more details you'll have to give more details and context.
I currently have a large SQL statement which i add the following line to in order to get the total cash for each transaction ID (which are unique):
select sum(cash) from Table a where a.branch = p.branch
and a.transID = p.transID) TotalCash
and i now need to do the same but only total the cash values that have a valuedate within the last month, so i have something like this:
select sum(CASE ValueDate WHEN > #startMonthDate THEN cash ELSE NULL END)
from Table a where a.branch = p.branch and a.transID = p.transID) TotalMonthCash
Sorry that I dont have the whole statement, but it is really long and specific to the context of the stored procedure but was hoping someone would know what i mean?
Try this instead:
SUM(CASE WHEN ValueDate > #startMonthDate THEN cash ELSE 0 END)
Explanation
Your CASE expression has incorrect syntax. It seems you are confusing the simple CASE expression syntax with the searched CASE expression syntax. See the documentation for CASE:
The CASE expression has two formats:
The simple CASE expression compares an expression to a set of simple expressions to determine the result.
The searched CASE expression evaluates a set of Boolean expressions to determine the result.
You want the searched CASE expression syntax:
CASE
WHEN Boolean_expression THEN result_expression [ ...n ]
[ ELSE else_result_expression ]
END
As a side note, if performance is an issue you may find that this expression runs more quickly if you rewrite using a JOIN and GROUP BY instead of using a dependent subquery.
Try moving ValueDate:
select sum(CASE
WHEN ValueDate > #startMonthDate THEN cash
ELSE 0
END)
from Table a
where a.branch = p.branch
and a.transID = p.transID
(reformatted for clarity)
You might also consider using '0' instead of NULL, as you are doing a sum. It works correctly both ways, but is maybe more indicitive of what your intentions are.
With condition HAVING you will eliminate data with cash not ultrapass 0 if you want, generating more efficiency
in your query.
SELECT SUM(cash) AS money FROM Table t1, Table2 t2 WHERE t1.branch = t2.branch
AND t1.transID = t2.transID
AND ValueDate > #startMonthDate HAVING money > 0;