Greatest of three columns in SQL - sql

I want to compare multiple columns and come with the maximum value among different columns
For three columns I came up with the below query which works fine
SELECT CASE
WHEN col1 >= col2
AND col1 >= col3 THEN col1
WHEN col2 >= col1
AND col2 >= col3 THEN col2
WHEN col3 >= col1
AND col3 >= col2 THEN col3
ELSE col1
END AS Max_number
FROM (VALUES (1,2,3),
(1,2,3),
(1,2,3)) tc (col1, col2, col3)
But things are getting complicated when I want to compare more than 3 columns. Is there any simpler way to do this

Try this Table Value Constructor trick
SELECT (SELECT Max(col)
FROM (VALUES (col1),
(col2),
(col3)) tc(col)) AS Max_number
FROM (VALUES (1,2,3),
(1,2,3),
(1,2,3)) tc (col1, col2, col3)
Additionally it handles NULL values as well

As a note, the logic using case is not as hard as it seems:
SELECT (CASE WHEN col1 >= col2 AND col1 >= col3 THEN col1
WHEN col2 >= col3 THEN col2
ELSE col3
END) AS Max_number
FROM (VALUES (1,2,3),
(1,2,3),
(1,2,3)
) tc (col1, col2, col3) ;
That is, you just need to compare the values in the order they are returned. Once a value is not the maximum, it doesn't need to be part of the comparison. So, for four values:
SELECT (CASE WHEN col0 >= col1 AND col0 >= col2 AND col0 >= col3 THEN col0
WHEN col1 >= col2 AND col1 >= col3 THEN col1
WHEN col2 >= col3 THEN col2
ELSE col3
END) AS Max_number
I prefer the method suggested by VR46, but want to point out that the CASE is not quite as bad as it seems.

Related

SQL union grouped by rows

Assume I have a table like this:
col1
col2
col3
col4
commonrow
one
two
null
commonrow
null
null
three
How to produce a result to look like this:
col1
col2
col3
col4
commonrow
one
two
three
Thanks
like this, you can group by col1 and get the maximum in each group:
select col1 , max(col2) col2 , max(col3) col3 , max(col4) col4
from table
group by col1

SQL Server: SELECT IF conditionally

I have a table with different columns and I need to show different based on the value of a specific column.
My table It's like this:
select col1, col2, col3, col4, col5, col6
from table1
So, for example:
if col1 = '1' --> show col3 and col4.
if col2 = '1' --> show col5 and col6
Use case expressions to chose columns to return. Note that a case's return types must be compatible, i.e. col3 and col5, and col4 and col6.
select case when col1 = 1 then col3
when col2 = 1 then col5
end,
case when col1 = 1 then col4
when col2 = 1 then col6
end
from tablename
Or, do a UNION ALL:
select col3, col4
from tablename where col1 = 1
union all
select col5, col6
from tablename where col2 = 1
Remaining questions - what do to if both col1 and col2 are 1? Or if none of them are?
Rule of thumb 1 : return to the caller the columns used for filtering.
Rule of thumb 2 : don't use union all, it returns duplicates and your result will not be a 'relation' (though in this case there would be no duplicates because col1 is a key but I still think union states the intent best).
select col1, col2, col3 AS colum_a, col4 AS colum_b
from table1
where col1 = 1
union
select col1, col2, col5 AS colum_a, col6 AS colum_b
from table1
where col2 = 1;

oracle sql query finding rows with multiple values in 3rd column matching columns 1 and 2

I have a dataset with about a million rows in and Oracle 11 db.
I'd like to find rows where col1 and col2 match but have different values in col3.
I'm not sure how to do this well though i can certainly write a query that never seems to finish:
select col1,col2,col3
from table tab1
where exists
(select 1
from table tab2
where tab1.col1 = tab2.col1
and tab1.col2 = tab2.col2
and tab1.col3 != tab2.col3);
I ran this and after an hour gave up waiting - I need to analyze the problems and present it to some people for figuring out how to move forward.
Thanks in any case,
Jeff
A query like this will indicate which rows having the same col1, col2 have differing values in col3:
SELECT col1, col2
FROM x
GROUP BY col1, col2
HAVING MIN(col3) <> MAX(col3)
To see how many of this col1, col2 pairs are affected:
SELECT COUNT(*)
FROM (SELECT col1, col2
FROM x
GROUP BY col1, col2
HAVING MIN(col3) <> MAX(col3)
)
You may also wish to know how many duplicates there are (ie having col1, col2, col3 the same:
SELECT col1, col2, col3
FROM x
GROUP BY col1, col2, col3
HAVING COUNT(*) > 1
Did you mean something like this?
select col1,col2,col3
from table tab1
where col1 = col2
and col1 <> col3

Filtering sql data with multiple filter vb.net (winform)

I want to filtering data from SQL to my datagrid.
I have :
1 table (tableX)
3 Columns
Col1 Col2 Col3
1/x/10 BJB 1/20/20
1/y/10 BJB 1/20/30
1/x/10 BJB 1/20/30
1/y/10 BJB 1/20/20
2 datagrid (dg1, dg2)
i want insert :
dg1 with col1 "1/x/10" and col3 "10/20/20"
dg2 with col1 "1/y/10 and col3 "10/20/20
i can filter with only one Col3
"SELECT Col1, Col2, Col3 FROM Tablex WHERE Col3='10/20/20'"
how to filter col1 witch contain "x" or "y" and col3?
==========================================================================
O YEAH.. thanks for the answer.
this for dg1
("SELECT Col1, Col2, Col3 FROM TableX WHERE Col1 like ('%/X/%') AND Col3='10/20/20'")
and this for dg2, the different is just X and Y..lol
("SELECT Col1, Col2, Col3 FROM TableX WHERE Col1 like ('%/Y/%') AND Col3='10/20/20'")
SELECT Col1, Col2, Col3
FROM Tablex
WHERE Col3='10/20/20'
AND (COL1 like '%/x/%' or COL1 like '%/y/%')
SELECT Col1, Col2, Col3
FROM Tablex
WHERE COL1 IN ('1/x/10', '1/y/10')
AND Col3 = '10/20/20
Or you can make the COL1 filter more ambiguous.
SELECT Col1, Col2, Col3
FROM Tablex
WHERE COL1 IN ('%/x/%', '%/y/%')
AND Col3 = '10/20/20

SQL Downselect query results based on field duplication

I'm looking for a little help with a SQL query. (I am using Oracle.)
I have a query that is a union of 2 differing select statments. The resulting data looks like the following:
Col1 Col2 Col3
XXX ValA Val1
XXX ValB Val2
YYY ValA Val1
YYY ValA Val2
In this setup the Col1 = XXX are default values and Col1 = YYY are real values. Real values (YYY) should take precidence over default values. The actual values are defined via columns 2 and 3.
I'm looking to downselect those results into the following:
Col1 Col2 Col3
XXX ValB Val2
YYY ValA Val1
YYY ValA Val2
Notice that the first row was removed ... that's because there is a real value (YYY in row 3) took precidence over the default value (XXX).
Any thoughts on how to approach this?
You want to filter out all the rows where col2 and col3 appear with XXX and with another value.
You can implement this filter by doing appropriate counts in a subquery using the analytic functions:
select col1, col2, col3
from (select t.*,
count(*) over (partition by col2, col3) as numcombos,
sum(case when col1 = 'XXX' then 1 else 0 end) over (partition by col2, col3) as numxs
from t
) t
where numcombos = numxs or (col1 <> 'xxx')
My instinct is to use an analytic function:
select distinct
first_value(col1)
over (partition by col2, col3
order by case col1
when 'XXX' then 1
else 0 end asc) as col1,
col2,
col3
from table1
However, if the table is large and indexed, it might be better to solve this with a full outer join (which is possible because there are only two possible values):
select coalesce(rl.col1, dflt.col1) as col1,
coalesce(rl.col2, dflt.col2) as col2,
coalesce(rl.col3, dflt.col3) as col3
from (select * from table1 where col1 = 'XXX') dflt
full outer join (select * from table1 where col1 <> 'XXX') rl
on dflt.col2 = rl.col2 and dflt.col3 = rl.col3;
[Solution in SQLFiddle]
I think you could use a trick like this:
select
case when
max(case when col1<>'XXX' then col1 end) is null then 'XXX' else
max(case when col1<>'XXX' then col1 end) end as col1,
col2,
col3
from
your_table
group by col2, col3
I transform default value to null, then i group by col3. The maximum value between null and a value is the value you are looking for. This works on your example data, but it might not be exactly what you are looking for, it depends on how your real data is.