Select Case Multiple When Select Conditions Gives Error - sql

The code below works fine.
(SELECT (CASE
WHEN (PA.ACTOR_KIND = 5) THEN
(SELECT POP.KDS_TEKLIF_TUT_TL)
ELSE 0 END) AS Expr1) AS YKF_CUSTOMER_LIMIT
However,when I add another "when" condition it gives error.
(SELECT (CASE
WHEN (PA.ACTOR_KIND = 5) THEN
(SELECT POP.KDS_TEKLIF_TUT_TL)
WHEN (PA.ACTOR_KIND = 10) THEN
(SELECT POP.KDS_ALICI_LIM_TL)
ELSE 0 END) AS Expr1) AS YKF_CUSTOMER_LIMIT
It seems all logical to me but not for sql
**Edit It was caused by typo error,there is nothing wrong with those statements.

I don't know if this will fix your problem, but you don't need SELECT for the WHEN clauses:
SELECT (CASE WHEN PA.ACTOR_KIND = 5
THEN POP.KDS_TEKLIF_TUT_TL
WHEN PA.ACTOR_KIND = 10
THEN POP.KDS_ALICI_LIM_TL
ELSE 0
END) AS YKF_CUSTOMER_LIMIT
You don't need to give the expression a name in the subquery as well as in the outer query. One name is enough. (Although that doesn't cause your error.)

Related

Why Would Unknown Column Be Referenced in SQL Query

I am in the process of updating some SQL queries to run against MariaDB instead of via SQL Anywhere. One query I'm running is erroring with this:
Error Code: 1054. Unknown column 'choice' in 'field list'
That is for this query:
SELECT
(select firstname||' '||lastname||' ('||service||')' from staff_members where id_number = customer_assignment_reviews.staff_member_id) as Rep,
(select customer_firstname||' '|| customer_lastname from customers where id_number = customer_assignment_reviews.cs_id) as Cus,
last_modified as "Response Date",replace(review_reason,'’','') as "Reason",
(Select choice = CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as "Accepted?"
FROM customer_assignment_reviews
where staff_member_id in (Select id_number from kar.staff_members where division_id = 6)
and "Response Date" between today() - 7 and today() /* Date Range */
and "Accepted?" = 'No'
Order by 3 desc
Is this error message as straightforward as it sounds? It's simply saying the column "choice" doesn't exist on the target table?
I'm just trying to reason through why this code (which I inherited) would be referencing a column that does not exist. Could something be expected here at runtime?
You don't need to use subquery in SELECT list
SELECT
-- ...
(Select choice = CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as "Accepted?"
=>
SELECT
CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end as "Accepted?"
Additionaly syntax SELECT alias = expression is only T-SQL specific:
SELECT alias = 1
<=>
SELECT 1 AS alias
What is this supposed to mean?
(Select choice = CASE
when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as "Accepted?"
Very importantly, a select is not needed here. You might mean:
(case when accepted = 0 then 'No'
when accepted = 1 then 'Yes'
end) as is_accepted -- prefer to not have to need escape characters
If accepted only takes those two values, you can simplify this to:
elt(accepted + 1, 'No', 'Yes') as is_accepted

SQL : select a comparison ? eg, a boolean result?

I was wondering if something like this was possible in SQL :
select (
(select count(*) from T) = (select count(*) from T t where t.something = thing)
)
This is probably very far from the actual SQL if it is possible, I don't write database requests so often.
How could I get the result of my comparison with a single request ? Basically, if I had no time, I would just make two requests and compare the results in Java (boooooo !! I know).
Although your query should work, the following is probably faster because only a single query is needed
select total_count = thing_count
from (
select count(*) as total_count,
sum(case when something = 42 then 1 end) as thing_count
from t
) t
The above is ANSI SQL and should work in any DBMS supporting a real boolean type. In Oracle you would need to use an expression in the outer select:
select case when total_count = thing_count then 1 else 0 end
from (
select count(*) as total_count,
sum(case when something = 42 then 1 end) as thing_count
from t
) t
I would write your query like this:
SELECT (CASE WHEN (select count(*) from T) = (select count(*) from T t where t.something = thing) THEN 1 ELSE 0 END)
However, if the first T is the same as the second T then what you actually want to check is if there are any records where t.something <> thing .. right ?
In that case you could simply do :
SELECT (CASE WHEN EXISTS (select * from T t where t.something != thing) THEN 1 ELSE 0 END)

How to do a SUM() inside a case statement in SQL server

I want to add some calculation inside my case statement to dynamically create the contents of a new column but I get the error:
Column 'Test1.qrank' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
This is the code I'm working on
case
when test1.TotalType = 'Average' then Test2.avgscore
when test1.TotalType = 'PercentOfTot' then (cnt/SUM(test1.qrank))
else cnt
end as displayscore
I did try to group but it didn't work.
Any hints?
The error you posted can happen when you're using a clause in the GROUP BY statement without including it in the select.
Example
This one works!
SELECT t.device,
SUM(case when transits.direction = 1 then 1 else 0 end) ,
SUM(case when transits.direction = 0 then 1 else 0 end) from t1 t
where t.device in ('A','B') group by t.device
This one not (omitted t.device from the select)
SELECT
SUM(case when transits.direction = 1 then 1 else 0 end) ,
SUM(case when transits.direction = 0 then 1 else 0 end) from t1 t
where t.device in ('A','B') group by t.device
This will produce your error complaining that I'm grouping for something that is not included in the select
Please, provide all the query to get more support.
You could use a Common Table Expression to create the SUM first, join it to the table, and then use the WHEN to to get the value from the CTE or the original table as necessary.
WITH PercentageOfTotal (Id, Percentage)
AS
(
SELECT Id, (cnt / SUM(AreaId)) FROM dbo.MyTable GROUP BY Id
)
SELECT
CASE
WHEN o.TotalType = 'Average' THEN r.avgscore
WHEN o.TotalType = 'PercentOfTot' THEN pt.Percentage
ELSE o.cnt
END AS [displayscore]
FROM PercentageOfTotal pt
JOIN dbo.MyTable t ON pt.Id = t.Id
If you're using SQL Server 2005 or above, you can use the windowing function SUM() OVER ().
case
when test1.TotalType = 'Average' then Test2.avgscore
when test1.TotalType = 'PercentOfTot' then (cnt/SUM(test1.qrank) over ())
else cnt
end as displayscore
But it'll be better if you show your full query to get context of what you actually need.

SQL 2 counts with different filter

I have a table and I need calculate two aggregate functions with different conditions in one statement. How can I do this?
Pseudocode below:
SELECT count(CoumntA) *< 0*, count(CoumntA) * > 0*
FROM dbo.TableA
This is the same idea as tombom's answer, but with SQL Server syntax:
SELECT
SUM(CASE WHEN CoumntA < 0 THEN 1 ELSE 0 END) AS LessThanZero,
SUM(CASE WHEN CoumntA > 0 THEN 1 ELSE 0 END) AS GreaterThanZero
FROM TableA
As #tombom demonstrated, this can be done as a single query. But it doesn't mean that it should be.
SELECT
SUM(CASE WHEN CoumntA < 0 THEN 1 ELSE 0 END) AS less_than_zero,
SUM(CASE WHEN CoumntA > 0 THEN 1 ELSE 0 END) AS greater_than_zero
FROM
TableA
The time when this is not so good is...
- There is an index on CoumntA
- Most values (50% or more feels about right) are exactly zero
In that case, two queries will be faster. This is because each query can use the index to quickly home in on the section to be counted. In the end only counting the relevant records.
The example I gave, however, scans the whole table every time. Only once, but always the whole table. This is worth it when you're counting most of the records. In your case it looks liek you're counting most or all of them, and so this is probably a good way of doing it.
It is possible to do this in one select statement.
The way I've done it before is like this:
SELECT SUM(CASE WHEN ColumnA < 0 THEN 1 END) AS LessThanZero,
SUM(CASE WHEN ColumnA > 0 THEN 1 END) AS GreaterThanZero
FROM dbo.TableA
This is the correct MS SQL syntax and I believe this is a very efficient way of doing it.
Don't forget you are not covering the case when ColumnA = 0!
select '< 0' as filter, COUNT(0) as cnt from TableA where [condition 1]
union
select '> 0' as filter, COUNT(0) as cnt from TableA where [condition 2]
Be sure that condition 1 and condition 2 create a partition on the original set of records, otherwise same records could be counted in both groups.
For SQL Server, one way would be;
SELECT COUNT(CASE WHEN CoumntA<0 THEN 1 ELSE NULL END),
COUNT(CASE WHEN CoumntA>0 THEN 1 ELSE NULL END)
FROM dbo.TableA
Demo here.
SELECT
SUM(IF(CoumntA < 0, 1, 0)) AS lowerThanZero,
SUM(IF(CoumntA > 0, 1, 0)) AS greaterThanZero
FROM
TableA
Is it clear what's happening? Ask, if you have any more questions.
A shorter form would be
SELECT
SUM(CoumntA < 0) AS lowerThanZero,
SUM(CoumntA > 0) AS greaterThanZero
FROM
TableA
This is possible, since in MySQL a true condition is equal 1, a false condition is equal 0
EDIT: okay, okay, sorry, don't know why I thought it's about MySQL here.
See the other answers about correct syntax.

Query to get percent of a total using select(count)

I'm calculating the change in pain between day 1 and day 2.
There are two fields, Pain_Admit_Comfort and Pain_48_Hr_Comfort, the options in each is Yes/No.
I need to find everyone that had pain on Admit and is More Comfortable 2 days later.
This is the query. The first two statements return correct numbers. I can't figure out how to divide using the same statements as numerator and denominator.
select
(select COUNT (PAIN_48_HR_COMFORT_C)
FROM CASES WHERE PAIN_48_HR_COMFORT_C='Yes') as Forty_Eight_Hours,
(SELECT COUNT (PAIN_ADMIT_COMFORT_C)
FROM CASES WHERE PAIN_ADMIT_COMFORT_C='YES') as Admit_Uncomfort_Yes,
((select COUNT (PAIN_48_HR_COMFORT_C)
FROM CASES WHERE PAIN_48_HR_COMFORT_C='Yes')
/
(SELECT COUNT (PAIN_ADMIT_COMFORT_C)
FROM CASES WHERE PAIN_ADMIT_COMFORT_C='YES')) AS Percent_Changed
from CASES
Thanks
I don't spot any immediate problems with your statement but following statement should return the correct results and is perhaps a bit easier to read.
SELECT feh.Forty_Eight_Hours
, auy.Admit_Uncomfort_Yes
, Percent_Changed = CAST(feh.Forty_Eight_Hours AS FLOAT) / auy.Admit_Uncomfort_Yes
FROM (
SELECT Forty_Eight_Hours = COUNT(PAIN_48_HR_COMFORT_C)
FROM CASES
WHERE PAIN_48_HR_COMFORT_C = 'Yes'
) feh
CROSS APPLY (
SELECT Admit_Uncomfort_Yes = COUNT (PAIN_ADMIT_COMFORT_C)
FROM CASES
WHERE PAIN_ADMIT_COMFORT_C = 'Yes'
) auy
Your query, and the other answers, are very inefficient (multiple selects).
What you want is called a "pivot", and the most efficient way of coding it using just one select over the table (your query uses 4) is as follows:
select
sum(case when PAIN_48_HR_COMFORT_C = 'Yes' then 1 else 0 end) as Forty_Eight_Hours,
sum(case when PAIN_ADMIT_COMFORT_C = 'Yes' then 1 else 0 end) as Admit_Uncomfort_Yes
sum(case when PAIN_ADMIT_COMFORT_C = 'Yes' AND PAIN_48_HR_COMFORT_C = 'NO' then 1 else 0 end) as Improved_pain
FROM CASES
I'm not sure what the columns mean - you may need to change a 'YES' to 'NO' etc to get the "has"/"has not" pain correct.