SQL can I select column name as value - sql

Here is my table
I would like to select as below
The tch_col will get the column name which column value is not 0 and if it's all 0 give the value as 19.
Could we do this is in SQL?
pls check lane 97 here
the result should
The first answer maybe not works but still
Thank you

Using a UNION to collate multiple entries
SELECT tch_function,tch_part,9 AS tch_col FROM TCH WHERE tch_col_09 > 0
UNION
SELECT tch_function,tch_part,10 AS tch_col FROM TCH WHERE tch_col_10 > 0
UNION
SELECT tch_function,tch_part,11 AS tch_col FROM TCH WHERE tch_col_11 > 0
UNION
SELECT tch_function,tch_part,12 AS tch_col FROM TCH WHERE tch_col_12 > 0
UNION
SELECT tch_function,tch_part,13 AS tch_col FROM TCH WHERE tch_col_13 > 0
UNION
SELECT tch_function,tch_part,14 AS tch_col FROM TCH WHERE tch_col_14 > 0
UNION
SELECT tch_function,tch_part,15 AS tch_col FROM TCH WHERE tch_col_15 > 0
UNION
SELECT tch_function,tch_part,16 AS tch_col FROM TCH WHERE tch_col_16 > 0
UNION
SELECT tch_function,tch_part,17 AS tch_col FROM TCH WHERE tch_col_17 > 0
UNION
SELECT tch_function,tch_part,18 AS tch_col FROM TCH WHERE tch_col_18 > 0
UNION
SELECT tch_function,tch_part,19 AS tch_col FROM TCH
WHERE tch_col_09 = 0 AND tch_col_10 = 0 AND tch_col_11 = 0
AND tch_col_12 = 0 AND tch_col_13 = 0 AND tch_col_14 = 0
AND tch_col_15 = 0 AND tch_col_16 = 0 AND tch_col_17 = 0
AND tch_col_18 = 0
ORDER BY 1,2

From discussion in comments: this is for SQL Server; so using a view to create the 19 column followed by the UNPIVOT operator should simplify things.
Original answer for standard SQL follows for posterity:
You can get the result you describe (with most major SQL databases; if you're using something old or obscure this may not work).
But it's not quite as pretty as selecting the column name. The following SQL is dependent on which specific columns are in the table; see notes afterward.
If you need a record for every non-0 value, it's going to be quite bad.
SELECT tch_function, tch_part, 9
FROM your_table
WHERE tch_col_09 <> 0
UNION ALL
SELECT tch_function, tch_part, 10
FROM your_table
WHERE tch_col_10 <> 0
-- you can see where this is going, right?
-- union in another select for each column
The problem here is that standard SQL isn't good about creating an undetermined number of result rows from each input row, other than during a join.
Now if you can get your hands on a relation with a single column containing the numbers from 9 through 19, you could do a cross join with that and then filter out the rows you don't want (WHERE (your_table.tch_col_09<>0 AND ref.value=9) OR ... OR (your_table.tch_col_09=0 AND ... AND your_table.tch_col_18=0 AND ref.value=19)); but it's still cumbersome, isn't it? You could use a DB2 VALUES subquery, or a temp table, or whatever to get such a relation if you decide to go that route...
If you could assume that only one column has a non-0 value, or if you'd be happy with just the name of the column containing the first non-0 value, it'd be less ugly:
SELECT tch_function
, tch_part
, case when tch_col_09 <> 0 then 9
when tch_col_10 <> 0 then 10
when tch_col_11 <> 0 then 11
when tch_col_12 <> 0 then 12
when tch_col_13 <> 0 then 13
when tch_col_14 <> 0 then 14
when tch_col_15 <> 0 then 15
when tch_col_16 <> 0 then 16
when tch_col_17 <> 0 then 17
when tch_col_18 <> 0 then 18
else 19
end as tch_col
from your_table
The case structure will return the value for the first matching THEN clause, or 19 if none of the THEN clauses match.
But it sounds like that won't do.
Lastly - Any of these queries would have to change if the set of TCH_COL_n columns in the table were to change; at a minimum a good relational table structure should lead to a fairly static set of columns.
More to the point, if you could change your table structure or use a processing language other than SQL you'd be in better shape.

Related

Add custom bool column where data is calculated based on values from linked entities

I have 2 tables: Entity and EntityItem.
EntityItems table has a Reason column which is nullable enum.
I'm trying to write a view that would return some Entititys columns and additionally a boolean column that states whether all corresponding EntityItem.Reason have a non-null value.
The following query returns somewhat what I want:
SELECT EntityItem.Id, COUNT(EntityItem.Reason) As Test
FROM EntityItem
GROUP BY EntityItem.ParentEntityId
ORDER BY Test DESC
Example output:
Id Test
132189 4
132190 2
132197 1
1 0
2 0
3 0
4 0
5 0
6 0
However, when I try to add this to a final query I get duplicated lines for each EntityItem
SELECT [Entity].[Id],
...
(SELECT CASE WHEN (SELECT COUNT([EntityItem].[Reason]) FROM [EntityItem] WHERE [EntityItem].[ParentEntityId] = [Entity].[Id]) = 0
THEN 0
ELSE 1
END) AS Test
FROM [Entity]
...
LEFT JOIN [EntityItem] ON [Entity].[Id] = [EntityItem].[ParentEntityId]
Example output:
Id Test
1 1
1 1
2 0
2 0
2 0
2 0
3 1
3 1
4 0
Question 1: Is my approach correct?
Question 2: Is there a way to remove duplicated lines without DISTINCT?
For your second query you need to aggregate before joining, for example by using outer apply something like:
select e.Id,
case when i.cnt = 0 then 0 else 1 end as Test
from Entity e
outer apply (
select Count(Reason) cnt
from EntityItem i
where i.ParentEntityId = e.Id
)i;
Saying that, since you are always returning a value of 1 if the count is greater than zero you don't actually need to count anything:
select e.Id,
case when exists (
select * from EntityItem i
where i.ParentEntityId = e.Id
)
then 1 else 0 end as Test
from Entity e;

What is the most efficient way to locate rows where 3 columns are not null?

My co worker asked me for help writing a query, and the question was this:
How can I return all rows from a table where all three columns B, C, and D are not null and they all contain positive or negative numbers.
I quickly gave him the following where clause that he says satisfies what he needed but I cannot verify as I don't have access to that specific database. This is what I told him to try:
select * from table_name
where ( nvl(B,0) + nvl(C,0) + nvl(D,0) ) <> 0 ;
This was off the top of my head a couple days back but i saw it in my email again so now i'm genuinely curious, Is there some glaring obvious way that would be better to accomplish this that i'm missing?
If I understand correctly, you can just use:
select t.*
from t
where a <> 0 and b <> 0 and c <> 0;
The <> filters out NULL values and zeros.
The question may be ambiguous and really be that the signs are all the same. If so:
where (a > 0 and b > 0 and c > 0) or
(a < 0 and b < 0 and c < 0)
since you need rows where some cols might be nulls but not all of them, try the following "where clause
where a <> 0 or b <> 0 or c <> 0;
that will get you any rows where at least one column is not null
with t (b,c,d) as (
select null,null,null from dual union all
select null,null,1 from dual union all
select null,1,2 from dual union all
select 1,2,3 from dual union all
select 2,2,2 from dual
)
select * from t where coalesce(b, c, d) is not null

returning the column values as a list or else 0

I had a query where i am trying to get the results of a query, the query can have multiple rows or it can be empty, i am trying if it is empty, it should return me 0 for a column i am looking which is called as sequence
My query is like this:
select CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END AS Sequence
from dbo.mytable
it returns me the either 1 or 0, for 1 i want that column should return me values or it should combine all the rows and return me the value of that column as list like 1,2,3,4,5,6,7
This should work.
SELECT
CASE WHEN MY_COUNT > 0 THEN 1 ELSE 0 END AS SEQUENCE
FROM
(SELECT COUNT(*) AS MY_COUNT
FROM
DBO.MYTABLE);
If you want only one row in the result set, simply do:
select (case when count(*) > 0 then 1 else 0 end) as sequence
from mytable;
If you care at all about performance, the more efficient method is:
select (case when exists (select 1 from dbo.mytable) then 1 else 0
end) as sequence

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)

Return different rows for each column in a row

I have data which is presented in multiple rows and columns with 0 or 1 values. What I'm trying to do is create a unique row for each 1, but there are sometimes multiple 1's in a row. For ex:
**A B C D**
1 0 1 1
0 0 0 1
1 1 0 0
I would like to have return six rows, all in one column like so
**RETURN**
A
C
D
D
A
B
Thanks in advance!
You can do this with a union all statement:
select val
from ((select 'A' as val from t where A = 1) union all
(select 'B' from t where B = 1) union all
(select 'C' from t where C = 1) union all
(select 'D' from t where D = 1)
) t
As a note: I hope you have other columns that you can include in the output. SQL tables are, by definition, not ordered. So, you really have no idea in your example of the original source for any given value.