MySQL query finding max between columns where non-zero - mysql

Suppose I have the following data:
data
Names X1 X2 X3
Jimmy 1 3 0
Mark 2 0 0
Jimmy 4 0 5
I am having trouble writing a unique query. What I would like return is the last number for each row that is non-zero. So the result would look like
Names Want
Jimmy 3
Mark 2
Jimmy 5
Is there a way to do this?

If you have a finite number of columns, you can use a CASE statement:
SELECT name,
CASE WHEN x3 <> 0 THEN x3
WHEN x2 <> 0 THEN x2
ELSE x1 END AS want
FROM myTable;
Here is an SQL Fiddle example.

Related

SQL group by bit set?

Is there any way of grouping the results of a select by individual bits set in a column? That is, ignoring combinations of various bits (otherwise a simple group by column would suffice).
For example, assuming a table has the values 1 through 10 for the group-by column exactly once (presented below with binary representation to simplify the construction/verification of the following group-by statement result):
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
10 1010
the group-by effect I want to achieve would look like:
select <bit>, count(*), group_concat(<column>) from <table> group by <...>
0 5 1,3,5,7,9
1 5 2,3,6,7,10
2 4 4,5,6,7
3 3 8,9,10
assuming the first bit is "bit 0".
I'm using MySQL at the moment, so ideally a solution should work there; but I'd be interested in other RDBMS solutions, if any.
You would need to split the values up and then reaggregate. Something like this:
select n.n, group_concat(col1)
from t join
(select 0 as n union all select 1 union all select 2 union all select 3
) n
on (1 << n) & bits > 0
group by n;

How to perform airthmetic operation in SQL query when airthmatic operators are stored in SQL database

I have a table like this:
id a b operation c
-------------------------------
1 2 3 + 5
2 2 3 + 6
3 3 2 / 1
4 4 7 * 28
5 54 2 - 27
6 3 0 / 0
When we have to perform a simple arithmetic operation we simply use
select a+b from table;
I have to use the operation column to check the value of a operation b is equal to c or not
Using "case" would help in your ... case
select a,operation,b,'=',
CASE operation
WHEN '+' then a+b
WHEN '*' then a*b
WHEN '-' then a-b
WHEN '/' then if(b=0,'NAN',a/b)
else null
end AS c
from mytable;

Filtering duplicate rows based on multiple columns (QueryBuilder 4.2)

I've ran into a little difficulty when trying to filter top N results for a table.
Assume the following table:
ID, X, Y, Result0, Result1
-------------------------------
0 0 0 1 4
1 0 1 2 5
2 0 1 1 4
3 0 2 2 5
4 0 3 0 1
5 1 3 3 4
6 1 3 2 5
7 1 3 4 6
So, let's say I want to get the top 2 results for the highest Result0 value, using Result1 as a tie breaker if the Result0 values are equal, and having only distinct values for (X,Y),
if I'll run the following query:
$result = DB::table('table')
->orderBy('Result1', 'DSC')
->orderBy('Result0', 'DSC')
->take(300)
->get();
This code will return IDs 5,7, because they have the highest Result0 values, but the X,Y for these fields are identical, and I'd like to get only top result for distinct X,Y values.
I tried adding a
->groupBy('X','Y')
But it grouped the entries based on the database order of the entries (i.e the ID) rather than my sorting of that table.
Anyone has any idea how can I achieve my goal?

Average of rows Mysql ignore zero values

Hello I have a problem with the function avg. I have a table like this and I would like to take the average of each row. I also have the zero in some cells and would like to avoid count them.
data rep val1 val2 val3
1 a 0 3 3
2 a 1 4 0
3 a 1 1 1
4 a 1 3 0
And I would like this result
data AVG
1 3
2 2.5
3 1
4 2
thank you
Assuming you have at least one non-zero value:
SELECT data, (val1+val2+val3)/((val1!=0) + (val2!=0) + (val3!=0)) avg
FROM **table_name**
I think divide by zero returns null see manual, depending on your db settings, so you could do:
SELECT data, COALESCE((val1+val2+val3)/((val1!=0) + (val2!=0) + (val3!=0)),0) avg
FROM **table_name**
Any null values in a row will cause each query to always return null and 0 for the row respectively.

SQL - counting rows with specific value

I have a table that looks somewhat like this:
id value
1 0
1 1
1 2
1 0
1 1
2 2
2 1
2 1
2 0
3 0
3 2
3 0
Now for each id, I want to count the number of occurences of 0 and 1 and the number of occurences for that ID (the value can be any integer), so the end result should look something like this:
id n0 n1 total
1 2 2 5
2 1 2 4
3 2 0 3
I managed to get the first and last row with this statement:
SELECT id, COUNT(*) FROM mytable GROUP BY id;
But I'm sort of lost from here. Any pointers on how to achieve this without a huge statement?
With MySQL, you can use SUM(condition):
SELECT id, SUM(value=0) AS n0, SUM(value=1) AS n1, COUNT(*) AS total
FROM mytable
GROUP BY id
See it on sqlfiddle.
As #Zane commented above, the typical method is to use CASE expressions to perform the pivot.
SQL Server now has a PIVOT operator that you might see. DECODE() and IIF() were older approaches on Oracle and Access that you might still find lying around.