I want to order the query results by specific values.
Seems like I can use this:
SELECT
column
FROM
table
ORDER BY
IF(
FIELD(
id,
3,1,2
) = 0,
1,
0
) ASC,
FIELD(
id,
3,1,2
)
My problem is that 3,1,2 comes from another table column. Replacing 3,1,2 with (SELECT column from...) is not working properly. Because the SELECT returns the result as "3,1,2" and not as 3,1,2
I can also extract 3,1,2 one by one, but in this case i get error Subquery returns more than 1 row.
What's the solution here ?
Suppose that the statement that returns the values 3, 1, 2 is something like this:
SELECT somecolumn FROM sometable ORDER BY someothercolumn
then you can use GROUP_CONCAT() to create a comma separated string that contains these values:
SELECT GROUP_CONCAT(somecolumn ORDER BY someothercolumn) col FROM sometable
and then use FIND_IN_SET() instead of FIELD():
SELECT t.column
FROM table t
CROSS JOIN (SELECT GROUP_CONCAT(somecolumn col ORDER BY someothercolumn) FROM sometable) s
ORDER BY
SUBSTRING_INDEX(t.id, s.col) = 0,
SUBSTRING_INDEX(t.id, s.col)
I hope that I understood the logic that you want to apply to sort the table with your ORDER BY clause.
Related
I'm stuck.
I'm trying to query one of my tables to obtain the maximum 'canister_change_date' with grouped pairs 'canister_type' and 'test_cell'.
I've put together a table with some dummy data (below) If you want the create table schema, let me know and I'll put it in the comments.
The final result would either need to have the id's or the whole row with id.
expected result (below) would have id's - 1, 2, 3, 5, 7, 8
6 should be removed as matching pair (test_cell =4, canister_type=Carbon Monoxide) and 7 to be taken as it has the later 'canister_change_date' date.
The expect result would either need to have the id's or id's and rest of fields.
Thanks!
You can use GROUP BY on multiple columns just like that
SELECT COUNT(*) FROM my_table GROUP BY column1, column2
If you want to find row with highest value of some column then you will need HAVING clause and MAX() aggregate function. You can combine them like this
SELECT max_column, column1, column2
GROUP BY column1, column2
HAVING max_column = MAX(max_column)
This example assumes you want to find highest value of max_column for each unique pair of column1 and column2
With NOT EXISTS:
select t.* from tablename
where not exists (
select 1 from tablename
where test_cell = t.test_cell and canister_type = canister_type
and canister_change_date > t.canister_change_date
)
or if your version of MySql is 8.0+ and supports window functions:
select t.* from (
select *,
row_number() over (partition by test_cell, canister_type order by canister_change_date desc) rn
from tablename
) t
where t.rn = 1
I was just wondering what MySQL code could I use to find the most common value across a series of columns containing similar values.
SELECT `column`,
COUNT(`column`) AS `value_occurrence`
FROM `my_table`
GROUP BY `column`
ORDER BY `value_occurrence` DESC
LIMIT 1;
I know I can use the above code to the find most common value in a single column but how would I expand this to find the value in 3 columns?
Eg
Column 1: 1, 2, 2, 4
Column 2: 1, 3, 2, 1
Column 3: 1, 2, 2, 2
Result : 2
Use UNION to move all the columns into a single column.
SELECT col, COUNT(*) AS value_occurrence
FROM (
SELECT col1 AS col
FROM my_table
UNION ALL
SELECT col2 AS col
FROM my_table
UNION ALL
SELECT col3 AS col
FROM my_table) AS x
GROUP BY column
ORDER BY value_occurrence DESC
LIMIT 1
All you have to do is replace column in COUNT(column) with an asterisk (*). That is the universal selector for accessing all records of a table. Then in your ORDER BY clause, specify allColumns as the scope of the data you want to order it by.
select allColumns, count(*) as value_occurrence from dataTable
group by allColumns
order by value_occurrence desc, allColumns
LIMIT 1;
I have a MySQL table with columns and values like this:
Column "A": 1, 5, 3, 2, 3, 1, 4, 5, ...
Column "B": 11, 15, 10, 12, 13, 14, 15, 10, 11, ...
Column "C": .... etc.
There is multiple columns in table with repeating numeric values.
I want to find out unique values in each column. So for column "A" it would return 1,2,3,4,5.
Currently I am using this query for one column:
SELECT concat(A) FROM table GROUP BY A;
But I don't know how to do it for multiple columns
If it's a small enough set of values, you can use the GROUP_CONCAT aggregate function, with the DISTINCT keyword
For example:
SELECT GROUP_CONCAT(DISTINCT a ORDER BY a) AS a_values
, GROUP_CONCAT(DISTINCT b ORDER BY b) AS b_values
, GROUP_CONCAT(DISTINCT c ORDER BY c) AS c_values
FROM mytable
The length of the string returned by GROUP_CONCAT is limited by the max_group_concat_len variable (it's in the reference) and I think the max_allowed_packet also comes into play.
Compare the length of the string returned to max_group_concat_len to see if it's shorter, to know that the return string hasn't been silently truncated.
If you want to combine all of those values together, into a single distinct list, you could do something like this:
SELECT GROUP_CONCAT(DISTINCT val ORDER BY val) AS col_values
FROM ( SELECT a AS val FROM mytable
UNION
SELECT b FROM mytable
UNION
SELECT c FROM mytable
) v
EDIT
I was confused by the use of the CONCAT function in the query, and misread the specification. The queries above return a single row, and returns a result that looks EXACTLY like what OP specified:
1,2,3,4,5,...
If we want to return each value on a separate row, a result that looks like this:
val
---
1
2
3
4
5
Then the query from Tim3880's answer does that, but the outer query isn't really necessary.
I'd want to add an ORDER BY, and actually write the query like this:
(SELECT a AS val FROM mytable)
UNION
(SELECT b AS val FROM mytable)
UNION
(SELECT c AS val FROM mytable)
ORDER BY 1
EDIT
Added SQL Fiddle showing how I interpret the specification (table, columns, exemplar values), and results from SQL statements above... one statement returning distinct values as individual rows (query immediately above), and a statement returning a comma separated list (the first query in my answer.)
SQL Fiddle Example HERE http://sqlfiddle.com/#!9/3d61c/1
If we want to identify which column(s) a value appears in
SELECT v.val
, GROUP_CONCAT(DISTINCT v.col ORDER BY v.col) AS in_cols
, MAX(v.col='a') AS in_col_a
, MAX(v.col='b') AS in_col_b
, MAX(v.col='c') AS in_col_c
FROM (
SELECT a AS val, 'a' AS col FROM mytable
UNION
SELECT b AS val, 'b' AS col FROM mytable
UNION
SELECT c AS val, 'c' AS col FROM mytable
) v
GROUP BY v.val
ORDER BY v.val
If your query works for A, then you can do it for A, B, C using this:
SELECT A FROM
(
SELECT A FROM table
UNION
SELECT B FROM table
UNION
SELECT C FROM table
) e
as long as the three columns have compatible types.
I have a table with 3 columns (id, name, code) and 10 rows. Some of the rows don't have a code so that column is empty for some. What I'm trying to accomplish is SELECT the rows with code column not empty first ordered by last inserted followed by all rows with code column empty ordered by last inserted.
I have tried
(SELECT * from tablename WHERE code <> '' ORDER BY ID DESC) UNION
(SELECT * from tablename WHERE code = '' ORDER BY ID DESC)
The UNION works but the order does not. I have read here about other questions and found out adding ORDER BY like I added will not work and I should add it at the end but that would not help me accomplish what I want and will mix rows that have a code with rows that don't.
Is there a way to succeed with what I'm looking for?
I think you just need to put your sort logic in the ORDER BY clause
SELECT id, name, code
FROM tablename
ORDER BY code = '', ID desc;
Try this:
SELECT * FROM
(
(SELECT * from tablename WHERE code <> '' ORDER BY ID DESC)
UNION
(SELECT * from tablename WHERE code = '' ORDER BY ID DESC)
)tab ORDER BY ID DESC;
Or
SELECT * from tablename ORDER BY code DESC,ID DESC
Change ASC/DESC as per you want it to show
Desired result:
Return results ONLY for the first true encountered SELECT expression.
Explanation:
So, I have three different SELECT expresions:
SELECT * FROM table WHERE column1 = 'sometext' AND column2='1'
SELECT * FROM table WHERE column1 = 'someothertext' AND column2='2'
SELECT * FROM table WHERE column1 = 'somethirdtext' AND column2='3'
I want to have the results from 1. If 1. is returning NULL, I would like result from select number 2. If Select number 2. is returning NULL, I would like to use select number 3. and so on.
Please note that I am expecting more than one row to be returned for each condition that is true - and I only want the result from either SELECT 1) 2) or 3) (in that order)
It is important to only return results from the one single SELECT expression, so even if 2. and 3. would return something, I would only like results from 1.
The code I have right now is following that expected logic BUT when a I have more than one rows being returned by some of the below SELECTS, it gives me error:
1242 - Subquery returns more than 1 row
The code right now:
SELECT IFNULL( (SELECT * FROM table WHERE column = 'sometext'), IFNULL( (SELECT * FROM table WHERE column = 'someothertext'), IFNULL( (SELECT * FROM table WHERE column = 'somethirdtext'), 0 ) ) )
You're looking for COALESCE function.
SELECT COALESCE(
(SELECT col FROM t WHERE `column` = 'sometext'),
(SELECT col FROM t WHERE `column` = 'someothertext'),
(SELECT col FROM t WHERE `column` = 'somethirdtext')
);
-please, note that subquery should not return more than 1 row/column.
I would approach this slightly differently, since you can only return one row per condition anyway, I would use the following to limit the number of selects done:
SELECT *
FROM table
WHERE column IN ('sometext', 'someothertext', 'somethirdtext')
ORDER BY CASE column
WHEN 'sometext' THEN 1
WHEN 'someothertext' THEN 2
WHEN 'somethirdtext' THEN 3
END
LIMIT 1;
As pointed out in the comments, you can use FIELD for the sort too:
SELECT *
FROM table
WHERE column IN ('sometext', 'someothertext', 'somethirdtext')
ORDER BY FIELD(column, 'sometext', 'someothertext', 'somethirdtext')
LIMIT 1;
I think you can get multiple rows per condition using the following:
SELECT T.*
FROM Table T
INNER JOIN
( SELECT Column
FROM Table
WHERE column IN ('sometext', 'someothertext', 'somethirdtext')
ORDER BY FIELD(column, 'sometext', 'someothertext', 'somethirdtext')
LIMIT 1
) MinT
ON MinT.Column = T.Column;
Basically the subquery MinT does the same as before, ordering by whichever condition matches. Then gets the value for the column of the first match and limits the whole table to this value.
Example on SQL Fiddle
SELECT t.*
FROM
( SELECT o.column1, o.column2
FROM
( SELECT 1 AS ord, 'sometext' AS column1, '1' AS column2 UNION ALL
SELECT 2, 'someothertext', '2' UNION ALL
SELECT 3, 'somethirdtext', '3'
) AS o
WHERE EXISTS
( SELECT 1
FROM table AS td
WHERE td.column1 = o.column1
AND td.column2 = o.column2
)
ORDER BY o.ord
LIMIT 1
) AS d
JOIN
table AS t
ON t.column1 = d.column1
AND t.column2 = d.column2 ;
MySQL isn't my daily db so I might be off on this, but can't you just use LIMIT 1 on your subqueries?