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

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.

Related

How to check unique values in SQL

I have a table named Bank that contains a Bank_Values column. I need a calculated Bank_Value_Unique column to shows whether each Bank_Value exists somewhere else in the table (i.e. whether its count is greater than 1).
I prepared this query, but it does not work. Could anyone help me with this and/or modify this query?
SELECT
CASE
WHEN NULLIF(LTRIM(RTRIM(Bank_Value)), '') =
(SELECT Bank_Value
FROM [Bank]
GROUP BY Bank_Value
HAVING COUNT(*) = 1)
THEN '0' ELSE '1'
END AS Bank_Key_Unique
FROM [Bank]
A windowed count should work:
SELECT
*,
CASE
COUNT(*) OVER (PARTITION BY Bank_Value)
WHEN 1 THEN 1 ELSE 0
END AS Bank_Value_Unique
FROM
Bank
;
It works also, but I found solution also:
select CASE WHEN NULLIF(LTRIM(RTRIM(Bank_Value)),'') =
(select Bank_Value
from Bank
group by Bank_Value
having (count(distinct Bank_Value) > 2 )) THEN '1' ELSE '0' END AS
Bank_Value_Uniquness
from Bank
It was missing "distinct" in having part.

Group by query with rollup

I'm trying to make a query that shows me every region and then make a count to see how mano contracts I have per region, but somehow I'm getting an error on ROLLUP (BO2.area)
This is the query
SELECT
CASE WHEN BO2.area IS NULL THEN ISNULL(BO2.area, 'TOTAL') ELSE BO2.area END Area,
COUNT(BO.status = 'INSTALLED') Contracts
FROM
BO2
JOIN BO ON BO.bostamp = BO2.bo2stamp
GROUP BY
ROLLUP (BO2.area)
Should use GROUPING instead of a null check, and inside the aggregate you need a CASE expression. So:
SELECT
CASE WHEN GROUPING(BO2.area)=1 THEN 'TOTAL' ELSE BO2.area END Area,
SUM( CASE WHEN BO.status = 'INSTALLED' THEN 1 ELSE 0 END ) Contracts
FROM
BO2
JOIN BO ON BO.bostamp = BO2.bo2stamp
GROUP BY
ROLLUP (BO2.area)
your query fails because Area is number (I'm guessing) and you want to combine it to text , so you need to cast it to string:
SELECT
CASE WHEN GROUPING(BO2.area)=1 THEN (cast(BO2.area as varchar(100)),'TOTAL') ELSE BO2.area END as Area
, COUNT(CASE WHEN BO.status = 'INSTALLED' THEN 1 ELSE 0 END ) Contracts
FROM
BO2
JOIN BO ON BO.bostamp = BO2.bo2stamp
GROUP BY
ROLLUP (BO2.area)

Is there a way to contruct this kind of result using group by in sql?

I have a table which consists of data where in I'm having trouble counting the corresponding rows.
Here is the sample table:
I am expecting an output like this:
You can do conditional aggregation:
select
sum(case when result = 'X' then 1 else 0 end) count_x,
sum(case when result is null then 1 else 0 end) count_blank
from mytable
I assume that by blank you mean null. If not, then you can change the condition in the second sum() from result is null to result = ''.
If you are running MySQL, this can be shortened a little:
select
sum(result = 'X') count_x,
sum(result is null) count_blank
from mytable

Select Case Multiple When Select Conditions Gives Error

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.)

Counting all other types but the current one

I'm trying to write this query, that would calculate the average value of all the columns except the one that contains the type value, which I'm grouping the whole query by.
So for 4 types for example, each column in the resulting table will contain the average of all the other three type's values, i need to exclude the current type's rows.
As an example, if I was to calculate each type's average value for itself, the query would look like:
SELECT
SUM(some value) / COUNT(TYPE)
FROM TEMPTABLE
GROUP BY TYPE
Now I'm trying to calculate the other three's total average. Thanks.
You can do one query to get the distinct types, and LEFT JOIN the same table, checking for type-inequality:
SELECT t1.type,
SUM(t2.some_value) / COUNT(t2.type)
FROM ( SELECT DISTINCT type FROM temptable ) t1
LEFT JOIN temptable t2 ON ( t1.type <> t2.type )
GROUP BY t1.type
Since you only want the average, you could replace the line
FROM ( SELECT DISTINCT type FROM temptable ) t1
by
FROM temptable t1
but the first solution might perform better, since the number of rows is reduced earlier.
The starting point here is to make a cartesian join between your types and your temptable (guessing your tables structure is : type(id, type), valueTable(id, type_id, some_value))
The following query
SELECT t.type, SUM(vt.someValue) /
COUNT (*) AS sum FROM type t,
valueTable vt WHERE vt.type_id != t.id
GROUP BY t.type
should do the trick.
Will this do what you need?
(Possibly with another CASE statement to avoid divide by zero errors if there is a possibility none of a type might be returned, I've also not explicitly accounted for the case that type is NULL)
SELECT
SUM(CASE WHEN TYPE <> 'Type1' THEN someValue ELSE 0 END) /
SUM(CASE WHEN TYPE = 'Type1' THEN 1 ELSE 0 END) AS T1,
SUM(CASE WHEN TYPE <> 'Type2' THEN someValue ELSE 0 END) /
SUM(CASE WHEN TYPE = 'Type2' THEN 1 ELSE 0 END) AS T2,
SUM(CASE WHEN TYPE <> 'Type3' THEN someValue ELSE 0 END) /
SUM(CASE WHEN TYPE = 'Type3' THEN 1 ELSE 0 END) AS T3,
SUM(CASE WHEN TYPE <> 'Type4' THEN someValue ELSE 0 END) /
SUM(CASE WHEN TYPE = 'Type4' THEN 1 ELSE 0 END) AS T4
FROM TEMPTABLE
I think that you can just use this:
SELECT type, avg(col_01)
FROM myTable
GROUP BY type
Should work on Sybase too:
SELECT
SUM(some value) / SUM(CASE WHEN TYPE = 1 THEN 1 ELSE 0 END)
FROM TEMPTABLE
GROUP BY TYPE