Multicolumn order by a tuple - sql

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.

Related

How to sum non-null values from multiple columns (workaround for CASE WHEN limitation) Postgresql

So I essentially want to work around the fact that CASE WHEN stops executing when it finds its first TRUE return.
I'd like to sum every instance of a non-null value between multiple columns, and group these based on my ID. Example table:
id
input1
input2
input3
1
a
null
k
2
null
null
b
3
null
null
null
4
q
null
r
5
x
p
j
6
null
y
q
I would like the output of my function to be:
id
total_inputs
1
2
2
1
3
0
4
2
5
3
6
2
Any work arounds? Is a custom function in order to create a count of unique or non-null entries across multiple columns, grouped by row?
I know I can create a CTE and assign 1's to each non-null column but that seems tedious (my data set has 39 inputs) - and I'd like to have a reusable function I could use again in the future.
You could use a simple aggregation as the following:
Select id,
Count(input1) + Count(input2) + Count(input3) As total_inputs
From table_name
Group By id
Order By id
Noting that Count(inputX) = 0, where inputX is null.
See a demo.
We can simply use:
select ID,
case when input1 is not null then 1 else 0 end
+ case when input2 is not null then 1 else 0 end
+ ...
+ case when input39 is not null then 1 else 0 end as total_inputs
from ...
No need to group by if you want every row (or count, we are not aggregating rows - that is what COUNT()..GROUP BY is for), or CTE.
Also, for some PostgreSQL versions, there is a num_nulls function to count null parameters:
select
, 32-num_nulls(input1, input2, input3, ..., input32)

How to include attribute created by CASE WHEN in the WHERE clause in HIVE?

This is a simple example of the problem:
SELECT CASE WHEN a = 5 THEN 0 ELSE 1 END AS x
FROM table
WHERE x = 0;
I will get an error message that x is not amongst the possible column names.
Could anyone advise me how to solve this?
SELECT
CASE WHEN a = 5 THEN 0
ELSE 1
END AS x FROM table
WHERE
CASE WHEN a = 5 THEN 0
ELSE 1
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

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)

SQL qn:- Case expression

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