SQL qn:- Case expression - sql

I have data in table a that i want to quench and create into another table b. Wondering how to do this. I was thinking of doing nested CASE expressions. But is this do-able?
For eg:-
Table a:-
S En Eg
-0.2 7888 99
90 9000 788
100 999 888
I want to create another table b, that does this:-
select
CASE WHEN S < 0 then (S+1/En-Eg)
ELSE (S-1/En-Eg)) END AS Z
from a
I also want to compare Z with other values:-
If z > 0 then 'Good'
else 'Bad'
Something like that, can i do this inside table b as well?

You could "reuse" the CASE expression if you performed it in a subquery:
SELECT z, CASE WHEN z > 0 THEN 'Good' ELSE 'Bad' END AS zdesc
FROM (
SELECT CASE WHEN S < 0
THEN (S + 1 / En - Eg)
ELSE (S - 1 / En - Eg) END AS z
FROM a
) b

Related

Multicolumn order by a tuple

Lets supose I have a tabla A like:
bisac1
bisac2
bisac3
desire
x
y
z
10
y
z
x
8
z
y
x
6
x
y
p
20
r
y
z
13
x
s
z
1
a
y
l
12
a
x
k
2
x
p
w
1
I would like to be able to count the number of times any of these elements (x,y,z) appears in the cols (bisac1,bisac2,bisac3).
So, the expected result should be 3 for the first 3 rows, 2 for the next 3 and 1 for the last 3.
Seems the following should do what you require?
select
case when bisac1 in ('x','y','z') then 1 else 0 end +
case when bisac2 in ('x','y','z') then 1 else 0 end +
case when bisac3 in ('x','y','z') then 1 else 0 end
from t;
You can also use one case per letter instead of one case per column (Stu's approach). The result will be the same for your sample data:
SELECT
CASE WHEN 'x' IN (bisac1, bisac2, bisac3) THEN 1 ELSE 0 END +
CASE WHEN 'y' IN (bisac1, bisac2, bisac3) THEN 1 ELSE 0 END +
CASE WHEN 'z' IN (bisac1, bisac2, bisac3) THEN 1 ELSE 0 END
FROM yourtable;
The result will not be the same if the same letter occurs in different columns, For example, if your row looks like this:
bisac1
bisac2
bisac3
x
y
y
Then Stu's query will produce 3 as result, my query here 2. From your description, it is unclear to me if your sample data can contain such rows at all or if the two queries will always create the same result for your data.
And even if your data can include such rows, it's still unclear to me whether you want to get 3 or 2 as result.
So, summarized, it's up to you what exactly you want to use here.

using the variable from the case clause in "where" statment

In my SQL query I have a CASE clause. How can I use the variable name from the CASE in where statment. This is my query
SElECT
a,
b,
CASE
WHEN AVG(CAST([x] as DECIMAL(9,2))) = 0
THEN 0
ELSE AVG(CAST([y] as DECIMAL(9,2))) / AVG(CAST([x] as DECIMAL(9,2)))
END AS z
FROM magic_table
WHERE z > 0
GROUP BY a,b
here I can not grab the z in where clause. But How can I do it ? is there any other way of doing it ?
As Panagiotis Kanavos already commented you cant use column alias in where statement but you can put your whole case statement in HAVING clause like so:
SElECT
a,
b,
CASE
WHEN AVG(CAST([x] as DECIMAL(9,2))) = 0
THEN 0
ELSE AVG(CAST([y] as DECIMAL(9,2))) / AVG(CAST([x] as DECIMAL(9,2)))
END AS z
FROM magic_table
GROUP BY a,b
HAVING CASE
WHEN AVG(CAST([x] as DECIMAL(9,2))) = 0
THEN 0
ELSE AVG(CAST([y] as DECIMAL(9,2))) / AVG(CAST([x] as DECIMAL(9,2)))
END > 0

Trying to replicate a '=countifs' function from excel to SQL

I have an excel file with a table that looks like this:
A B C
Registry ID Parent Reg ID Focus Account (Y/N)
100000033 100000036778 Y
100000343 1000 Y
1000343223 100000036778 N
And the formula is on the column D (Focus Parent): =IF(COUNTIFS(C:C,"Y",B:B,B)>=1,"Y","N")
So on the column D the formula returns 'Y' for each row.
I've tried to replicate this in SQL with the following code:
SELECT
REGISTRY_ID,
PARENT_REG_ID,
FOCUS_ACCOUNT,
SCORE_DETAILS,
(CASE
WHEN FOCUS_ACCOUNT = 'Y' THEN
(CASE
WHEN COUNT(PARENT_REG_ID) >= 1 THEN 'Y'
ELSE 'N'
END)
ELSE 'N'
END) AS Focus_Parent
FROM MA_ACCOUNTS
But this query returns this error:
ORA-00937: not a single-group group function
Can you please advise?
Later edit:
Let me clarify this: I have a list with unique Registry_IDs that contain a Parent_Registry_ID. A Parent_Registry_ID can have multiple Registry_ID but if a Registry_ID is marked as ‘Y’ in the Column Focus_Account then that Parent_Registry_ID should have ‘Y’ in the column Focus_Parent.
Registry ID Parent Reg ID Focus Account (Y/N)
1 A N
2 B N
3 A Y
4 C Y
5 A N
6 B Y
7 A N
8 D Y
9 E N
10 E N
Expected outcome:
Registry ID Parent Reg ID Focus Account (Y/N) Focus Parent (Y/N)
1 A N Y
2 B N Y
3 A Y Y
4 C Y Y
5 A N Y
6 B Y Y
7 A N Y
8 D Y Y
9 E N N
10 E N N
You are using an aggregated count() so Oracle is expecting a GROUP BY clause. However, that would not fit the shape of your result set. Seems like an analytic function would be better?
You have posted a clarification which I think defines this rule:
if any registry_id has focus_account='Y' then set focus_parent = 'Y' for all instances of its parent_reg_id.
If my interpretation is correct you can implement it quite simply with an analytic max():
select
registry_id,
parent_reg_id,
focus_account,
max( focus_account ) over (partition by parent_reg_id) as focus_parent
from ma_accounts
This works because focus_account is a Y/N flag. Certainly the above query produces your revised result set from the posted input data.
Your using an aggregate method in the select section, but your not grouping at the end for the other selected variables.
Try:
SELECT
REGISTRY_ID,
PARENT_REG_ID,
FOCUS_ACCOUNT,
SCORE_DETAILS,
CASE WHEN COUNT(PARENT_REG_ID) >= 1 AND FOCUS_ACCOUNT = 'Y' THEN 'Y'
ELSE 'N' END AS Focus_Parent
FROM MA_ACCOUNTS
GROUP BY REGISTRY_ID,
PARENT_REG_ID,
FOCUS_ACCOUNT,
SCORE_DETAILS

SQL Case with sum and normal value

Below is my SQL query
select
case when x < 2 then a
when x = 0 then Max(a) end a
,case when x < 2 then b
when x = 0 then Sum(b) end b
from T
How can we do this? I am using right now Union to get the required result. Looking for a better way to do this.
You can get these aggregate values into a variable and use it.
DECLARE #maxA int;
DECLARE #sumB int;
SELECT #maxA = max(a),#sumB = sum(b) FROM t;
SELECT CASE
WHEN x < 2 THEN a
WHEN x = 0 THEN #maxA
END a ,
CASE
WHEN x < 2 THEN b
WHEN x = 0 THEN #sumB
END b
FROM T
You can use CASE When conditions inside the Aggregate functions.
i.e.
SELECT SUM(CASE WHEN x < 2 THEN a WHEN x = 0 THEN #maxA END) AS sum_a

Even or odd in SQL

This is table structure
id
1
2
3
4
5
6
I need result like this
id even odd
1 0 1
2 1 0
3 0 1
4 1 0
5 0 1
6 1 0
I tried
select id %2=0 then 1 else 0 end or id%2 <>0 then 1 else 0 odd
from table
How about
select
id,
~id & 1,
id & 1
from t
Take a look at the CASE keyword. It works very similarly to what you're trying to do in your SELECT statement. In addition, if you want to select multiple columns, separate them with a comma. The OR keyword is used for combining logical conditions in your query, not for specifying multiple columns.
An example of how you could use CASE in your query would be as follows:
SELECT id,
CASE WHEN id %2=0 THEN 1 ELSE 0 END AS Even,
[column2]
FROM [TableName]
The table structure is just Id?
you could try this!
select *,
case when id %2=0 then 1 else 0 end as even,
case when id %2 <>0 then 1 else 0 end as odd
from table
You have the right idea, but your syntax is a bit off. I'd use a CASE statement to create the even column, and then a calculate odd accordingly:
SELECT id, even, ABS(even - 1) AS odd
FROM (SELECT id, CASE WHEN id % 2 = 0 THEN 1 ELSE 0 END AS even
FROM my_table)