How to address multiple columns as one in MySQL? - mysql

Columns a, b and c contain some values of the same nature. I need to select all the unique values. If I had just one column I'd use something like
SELECT DISTINCT a FROM mytable ORDER BY a;
but I need to treat a, b and c columns as one and gett all the unique values ever occurring among them.
As an example, let this be a CSV representation of mytable, the first row naming the columns:
a, b, c
1, 2, 3
1, 3, 4
5, 7, 1
The result of the query is to be:
1
2
3
4
5
7
UPDATE: I don't understand why do all of you suggest wrapping it in an extra SELECT? It seems to me that the answer is
(SELECT `a` AS `result` FROM `mytable`)
UNION (SELECT `b` FROM `mytable`)
UNION (SELECT `c` FROM `mytable`)
ORDER BY `result`;
isn't it?

So you want one column all with unique values from a, b and c? Try this:
(select a as yourField from d1)
union
(select b from d2)
union
(select c from d3)
order by yourField desc
limit 5
Working example
Edited after requirements changed... There you have the order by and limit you requested. Of course, you'll get only 5 records in this example

sorry i miss understood your question. here is updated query.
select a from my table
UNION
select b from my table
UNION
select c from my table

SELECT tmp.a
FROM
(SELECT column_1 AS a
FROM table
UNION
SELECT column_2 AS a
FROM table
UNION
SELECT column_3 AS a
FROM table) AS tmp
ORDER BY `tmp`.`a` ASC

try this:
SELECT b.iResult
FROM
(SELECT a as iResult FROM tableName
UNION
SELECT b as iResult FROM tableName
UNION
SELECT c as iResult FROM tableName) b
ORDER BY b.iResult
LIMIT BY 10 -- or put any number you want to limit.

Related

How do I find duplicate values across multiple columns in Mysql?

I have a table like this
I want to check the all rows in Column A with column B and get the count of duplicates.
For example, I want to get the
count of 12 as 3(2 times in A+1 time in B)
count of 11 as 2(2 times in A+0 time in B)
count of 13 as 2(1 time in A+0 time in B)
How can I acheive it?
You can calculate the total occurrences from a union all. A where clause can show only the values that occur in the A column:
select nr
, count(*)
from (
select A as nr
from YourTable
union all
select B
from YourTable
) sub
where nr in -- only values that occur at least once in the A column
(
select A
from YourTable
)
group by
nr
having count(*) > 1 -- show only duplicates
You can combine all values in A and B then do the group by.
Then only select those values found in column A.
Select A, count(A) as cnt
From (
Select A
from yourTable
Union All
Select B
from yourTable) t
Where t.A in
(select distinct A from yourTable)
Group by t.A
Order by t.A;
Result:
A cnt
11 2
12 3
13 1
See demo: http://sqlfiddle.com/#!9/9fcfe9/3

repeat result multiple times in mysql

I have a table having id and no field, what I really want is the result raw will be repeated no filed times, if the no field is 2 then that raw must be repeated twice in result.
this is my sample table structure:
id no
1 3
2 2
3 1
now I need to get a result like:
1 3
1 3
1 3
2 2
2 2
3 1
I tried to write mysql query to get the result like above, but failed.
You need a table of numbers to accomplish this. For just three values, this is easy:
select t.id, t.no
from t join
(select 1 as n union all select 2 union all select 3
) n
on t.no <= n.no;
This query must do what you want to achieve:
select t.id, t.no from test t cross join test y where t.id>=y.id
not completely solve your problem, but this one can help
set #i=0;
select
test_table.*
from
test_table
join
(select
#i:=#i+1 as i
from
any_table_with_number_of_rows_greater_than_max_no_of_test_table
where
#i < (select max(no) from test_table)) tmp on no >= i
order by
id desc
EDIT :
This is on SQL Server. I checked online and see that CTEs work on MySQL too. Just couldn't get them to work on SQLFiddle
Try this, remove unwanted columns
create table #temp (id int, no int)
insert into #temp values (1, 2),(2, 3),(3, 5)
select * from #temp
;with cte as
(
select id, no, no-1 nom from #temp
union all
select c.id, c.no, c.nom-1 from cte c inner join #temp t on t.id = c.id and c.nom < t.no and c.nom > 0
)
select * from cte order by 1
drop table #temp

GROUP_CONCAT on two tables

I have two tables, with independent ids (can't be connected via joins), I want to query and get a GROUP_CONCAT of both columns.
Example: table "a" has ids: 1, 2, 3. table "b" has the ids: 10, 11.
End result should be: 1, 2, 3, 10, 11
I have tried a few queries:
SELECT CONCAT_WS(',', GROUP_CONCAT(a.id), GROUP_CONCAT(b.id)) AS combined FROM a, b
SELECT GROUP_CONCAT(a.id, b.id) AS combined FROM a, b
These queries are returning me duplicate results though 8as in, all results from a twice and all results from b twice as well)
Try union all:
select group_concat(ab.id) as ids
from ((select id from a
) union all
(select id from b
)
) ab;
Your queries are doing cross join's between the tables, so data after the cross join is:
a.id b.id
1 10
1 11
2 10
2 11
3 10
3 11
After the union all, the data is:
ab.id
1
2
3
10
11
GROUP_CONCAT(DISTINCT [])
will help
https://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
The following query will generate that you want.
You can play with the table_position dynamic column for deciding which table goes first.
Select group_concat(id order by table_position) from
(
select id, 1 as table_position from a
union all
select id, 2 as table_position from b
)
If you want duplicates, use union all. If you don't want duplicates, use union.
In either case, the query you need is as follows:
select group_concat(id) from
(select id from a
union
select id from b) as ids;

UNION ignores column names?

Why does
select 1 as a, 2 as b
union all
select 20 as b, 10 as a
returns
a b
1 2
20 10
instead of
a b
1 2
10 20
?
Is there a way to make union match column names?
Nope, selecting them in order is required with UNION.
Column names are only pertinent for the first part of the union to deifne the union columns. Other unions will join in the same order the columns are given from the first select and often have differn names. If you want want to relate the first column to the second column, You can't. However you can adjust your second select statment to put the columns in the correct order.
Union only looks at the number of columns, and their relative positions in the query string. it does NOT mix-match based on aliases or the source column names. e.g. You could have two completely different tables:
SELECT x,y FROM foo
UNION
SELECT p,q FROM bar
What should MySQL do in this case? return a single row
x,y,p,q
because none of the column names match? Nope. That'd be incorrect.
I'm not sure if this solves your problem, but you can use subqueries within the union to put the columns in the "right" order:
(select a, b from (select 1 as a, 2 as b) t)
union all
(select a, b from (select 20 as b, 10 as a) t)
I realize the question is tagged MySQL, which doesn't support full outer join. If it did, you could do do the union all as:
select coalesce(t1.a, t2.a) as a, coalesce(t1.b, t2.b) as b
from (select 1 as a, 2 as b) t1 full outer join
(select 20 as b, 10 as a) t2
on 0 = 1;
You can do this in MySQL. This assumes that none of your values are never NULL:
select coalesce(t1.a, t2.a) as a, coalesce(t1.b, t2.b) as b
from (select 1 as a, 2 as b union all select NULL, NULL) t1 join
(select 20 as b, 10 as a union all select NULL, NULL) t2
on (t1.a is null or t2.a is null) and coalesce(t1.a, t2.a) is not null

MySQL, SELECT * FROM t WHERE c={The most duplicated entry}

Pretty much as the title says, that was the simplest way I could explain it. To elaborate...
I first need to find the value of column c that has been duplicated the most times (mostDuplicated), and then SELECT * FROM t WHERE c=mostDuplicated
To go on about it further...
Here's my data:
SELECT * FROM t
a, b, c
- - -
1, 1, 1
2, 2, 1
3, 3, 1
4, 4, 2
5, 5, 3
So ignore the values in columns a & b completely, just concentrate on column c. I need to find the most duplicated value in column c (which is 1), and then SELECT only these records WHERE c=1. I want to do this in a single query if possible.
Do a "group by" query to count the number of unique values of c, order it descending and select only the top row. Then use the output as a subquery to select rows with that particular value of c:
SELECT * FROM t WHERE c = (SELECT c FROM t GROUP BY c ORDER BY COUNT(*) DESC LIMIT 1)
SELECT c FROM t GROUP BY c ORDER BY count(*) DESC LIMIT 1
Well it will be, like this:
SELECT * FROM t WHERE c =
(SELECT c FROM
(SELECT c, count(c) as co
FROM t ORDER BY co DESC LIMIT 1))
Hope this help
Here you go, it's a bit convoluted:
SELECT
*
FROM
t
WHERE
(
c IN
(
SELECT c
FROM (
SELECT
c,
COUNT(c) as freq
FROM
t
GROUP BY
c
ORDER BY
freq DESC,
c ASC
LIMIT 1
) AS t2
)
)
Basically, it's going this:
1. determine how often each value of C is repeated
2. select the value of the MAXimum repeats
3. use that value to determine what value of C to use when select * from the entire table.