Reputation: 103
I have some 8 columns in a table.All the columns are of same type integer.
|id | marks_1 | marks_2 | marks_3|....|marks_7|
|1001|0 |20 |15 |....|25 |
|1002|20 |0 |11 |....|0 |
.
.
.
.
|1010|40 |0 |0 |....|25 |
I want to get the output as
|id |marks |
|1001|15 |
|1002|11 |
I tried getting the least of these columns using the LEAST() function of MySql.
SELECT id, LEAST(marks_1,marks_2,marks_3,marks_4,marks_5,marks_6,marks_7) AS marks from tbl_name
and it is working.
It fetches me
|id |marks |
|1001|0 |
|1002|0 |
but I need the second least. i.e non-zero record from the row.
Upvotes: 2
Views: 256
Reputation: 1093
try this:
SELECT t1.id, IFNULL(LEAST(COALESCE(NULLIF(t1.col_1, 0),NULLIF(t1.col_2, 0),NULLIF(t1.col_3, 0),NULLIF(t1.col_4, 0),NULLIF(t1.col_5, 0),NULLIF(t1.col_6, 0),NULLIF(t1.col_7, 0)),
COALESCE(NULLIF(t1.col_2, 0),NULLIF(t1.col_3, 0),NULLIF(t1.col_4, 0),NULLIF(t1.col_5, 0),NULLIF(t1.col_6, 0),NULLIF(t1.col_7, 0),NULLIF(t1.col_1, 0)),
COALESCE(NULLIF(t1.col_3, 0),NULLIF(t1.col_4, 0),NULLIF(t1.col_5, 0),NULLIF(t1.col_6, 0),NULLIF(t1.col_7, 0),NULLIF(t1.col_1, 0),NULLIF(t1.col_2, 0)),
COALESCE(NULLIF(t1.col_4, 0),NULLIF(t1.col_5, 0),NULLIF(t1.col_6, 0),NULLIF(t1.col_7, 0),NULLIF(t1.col_1, 0),NULLIF(t1.col_2, 0),NULLIF(t1.col_3, 0)),
COALESCE(NULLIF(t1.col_5, 0),NULLIF(t1.col_6, 0),NULLIF(t1.col_7, 0),NULLIF(t1.col_1, 0),NULLIF(t1.col_2, 0),NULLIF(t1.col_3, 0),NULLIF(t1.col_4, 0)),
COALESCE(NULLIF(t1.col_6, 0),NULLIF(t1.col_7, 0),NULLIF(t1.col_1, 0),NULLIF(t1.col_2, 0),NULLIF(t1.col_3, 0),NULLIF(t1.col_4, 0),NULLIF(t1.col_5, 0)),
COALESCE(NULLIF(t1.col_7, 0),NULLIF(t1.col_1, 0),NULLIF(t1.col_2, 0),NULLIF(t1.col_3, 0),NULLIF(t1.col_4, 0),NULLIF(t1.col_5, 0),NULLIF(t1.col_6, 0))),0) AS marks
from tbl_name t1
Upvotes: 2
Reputation: 15057
this is not nice, but also works:
SELECT
id
, SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(col1 ORDER BY col1), ',', -3),',',1)
FROM (
SELECT id, col1 FROM test_table
UNION SELECT id, col2 FROM test_table
UNION SELECT id, col3 FROM test_table
UNION SELECT id, col4 FROM test_table
UNION SELECT id, col5 FROM test_table
) AS t
GROUP BY t.id
ORDER BY t.col1
;
sample
mysql> SELECT
-> id
-> , SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(col1 ORDER BY col1), ',', -3),',',1)
-> FROM (
-> SELECT id, col1 FROM test_table
-> UNION SELECT id, col2 FROM test_table
-> UNION SELECT id, col3 FROM test_table
-> UNION SELECT id, col4 FROM test_table
-> UNION SELECT id, col5 FROM test_table
-> ) AS t
-> GROUP BY t.id
-> ORDER BY t.col1
-> ;
+----+-----------------------------------------------------------------------------------+
| id | SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(col1 ORDER BY col1), ',', -3),',',1) |
+----+-----------------------------------------------------------------------------------+
| 1 | 3 |
| 2 | 6 |
+----+-----------------------------------------------------------------------------------+
2 rows in set (0,00 sec)
mysql> select * from test_table;
+----+------+------+------+------+------+
| id | col1 | col2 | col3 | col4 | col5 |
+----+------+------+------+------+------+
| 1 | 1 | 3 | 2 | 5 | 4 |
| 2 | 7 | 8 | 6 | 3 | 2 |
+----+------+------+------+------+------+
2 rows in set (0,00 sec)
mysql>
Upvotes: 0
Reputation: 72165
If you what you want is the minimum number that is greater than 0
, then you can unpivot your table and apply grouping to it:
SELECT id, MIN(c)
FROM (
SELECT id,
CASE t2.n
WHEN 1 THEN col_1
WHEN 2 THEN col_2
WHEN 3 THEN col_3
WHEN 4 THEN col_4
WHEN 5 THEN col_5
WHEN 6 THEN col_6
WHEN 7 THEN col_7
END AS c
FROM mytable AS t1
CROSS JOIN (
SELECT 1 AS n UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
SELECT 6 UNION ALL
SELECT 7) AS t2) AS x
WHERE x.c > 0
GROUP BY id
Upvotes: 3
Reputation: 1269673
You can do this by normalizing the data and using variables:
select t.*
from (select t.*,
(@rn := if(@id = id, @rn + 1,
if(@id := id, 1, 1)
)
) as rn
from ((select id, col_1 as col, 'col_1' as colname from t) union all
(select id, col_2 as col, 'col_2' as colname from t) union all
. . .
) t cross join
(select @rn := 0, @id := -1) params
order by id, col asc
) t
where rn = 2;
Note: This version also gives the column name. You need to fill in the . . .
with all the other columns.
Upvotes: 1