MySQL: SELECT DISTINCT multiple columns, with the first result on some columns - mysql

Let's say I have columns a, b in a table in a MySQL database. What I'm trying to do is to select the distinct values of a with an arbitrary value of b - let's say the first one, but I actually don't care which one.
Something like the query below will give me all distinct values on both columns, so it is not good for me (too many results in my case).
SELECT DISTINCT a, b
FROM my_table;
Any suggestions?
In case I want 2 values of b for each a value, how is that possible?

Use the GROUP BY feature, like:
SELECT a, b
FROM my_table
GROUP BY a;
See my SQL Fiddle.
UPDATE
No DISTINCT is needed at all.
Thanks to dnoeth for the suggestion.

This is just a guess from what I think your'e trying to do:
SELECT DISTINCT a as distinct,
( SELECT b FROM my_table WHERE c = a LIMIT 1 ) as arbitary
FROM my_table;

Related

Generate list of distinct dimensions in a table

I have a table with 3 dimensions- A, B, and C.
I essentially want values of all possible combinations for these dimensions and populate all measures(M) as 0 when a combination isn't present.
Suppose I have the table-
If I do this I get -
select a,b,c from sum(m) fact group by a,b,c
But I would like all possible combinations, -
Currently, I a doing a cross join like below, but is there some faster way to do this (as my table has about ~1M records)? -
select * from (
select distinct f1.a, f2.b, f3.c
from fact f1
cross join fact f2
cross join fact f3 ) all
left join
( select a,b,c from sum(m) fact group by a,b,c) s
on all.a=s.a and all.b=s.b and all.c=s.c
If this is Oracle Database, then this is exactly what cube is for.
select a, b, c, sum(m)
from my_table
group by cube(a,b,c)
MySQL:
GROUP BY a,b,c will produce 1 row per combination that exists in the table.
If you want all possible combinations, you need to build 1 (or 3) more tables to list all the possible values, then do a LEFT JOIN from them. You may also want COALESCE(col, 0) to turn NULLs into zeros.

How to get the DISTICT (column) and then count them in Group In MYSQL?

I have A huge table with lots of data and fields.
I need to get the distinct values from some column,and count them in to groups based on another column .
I tried something like below, But it count of distinct values in each group.
I don't want to count same value in different groups.
Any help appreciated!
Thanks In advance .
select distinct(A) as A, count(distinct(B)) as count_b, C from `some_table` group by A,C
You can try below -
select A, count(distinct B) as count_b, C
from `some_table` group by A,C

Compare one table with another in mysql and display matched record

I have two mysql tabales.
Table1:opened_datatable
Table2:unidata
Table1 has only one column:Emails
Table2 has 45 columns, three of them are:Email_Office, Email_Personal1, Email_Personal2
I want to fetch full rows from Table2-unidata if Emails column of Table1 matches with either Email_Office or Email_Personal1 or Email_Personal2. I am getting little bit confused here.I tried this way:
select a.emails
from opened_datatable a
where a.Emails in (select *
from unidata b
where b.email_office=a.emails
or b.Email_Personal1=a.emails
or b.Email_Personal2=a.Emails
)
Its showing only one row of first table while I want to show matched rows of Table2 -unidata. First I need to mention table 2 and then I should have to match it with table 1-opened_datatable. But how can I do that?
Try This:
SELECT a.emails, b.*
FROM opened_datatable a
INNER JOIN unidata b ON a.emails IN (b.email_office, b.Email_Personal1, b.Email_Personal2)
Your current query should return an error.
Try a Corrrelated Subquery using EXISTS, quite similar to your apporach:
select a.emails
from opened_datatable a
where EXISTS
( select *
from unidata b
where b.email_office=a.emails
or b.Email_Personal1=a.emails
or b.Email_Personal2=a.Emails
)
You will probably not get good performance due to the OR-ed conditions.
Edit:
If performance is too bad, you might try a UNION approach:
select a.emails
from opened_datatable a
where a.emails
IN
( select email_office
from unidata b
UNION
select Email_Personal1
from unidata b
UNION
select b.Email_Personal2
from unidata b
)

join two different tables?

How can I join table a and table b and get records for each? Not an actual join... not sure what this is called.
So if I have 3 records in a, and 5 records in b, I want 8 records back.
In a record for a, all b fields can be null. In a record for b, all a fields can be null.
edit: My tables have different fields.
Error Code: 1222. The used SELECT statements have a different number of columns
Like the others mentionned, you need an union
SELECT intColumn, varcharColumn, intColumn FROM a
UNION
SELECT intColumn, varcharColumn, 0 FROM b
but you must have the same number of columns and they must also have similar data types.
Here's a good tutorial about it
Also, if you want columns that are not in both tables, you can fill with nulls or constants.
You want a UNION:
SELECT something FROM a
UNION
SELECT something FROM b
Try this
SELECT * FROM a
LEFT JOIN b ON a.id1 = b.id2
UNION
SELECT * FROM a
RIGHT JOIN b ON a.id1 = b.id2
Just make sure, that A and B have different IDs
Edit: Working Fiddle
You can also use some other field other then id which are not same in two table
Edit: Updated fiddle

How do I Concatenate entire result sets in MySQL?

I'm trying out the following query:
SELECT A,B,C FROM table WHERE field LIKE 'query%'
UNION
SELECT A,B,C FROM table WHERE field LIKE '%query'
UNION
SELECT A,B,C FROM table WHERE field LIKE '%query%'
GROUP BY B ORDER BY B ASC LIMIT 5
That's three queries stuck together, kinda sorta. However, the result set that comes back reflects results from query #3 before the results from query #1 which is undesired.
Is there any way to prioritize these so that results come as all for query #1, then all for query #2 then all for query #3? I don't want to do this in PHP just yet (not to mention having to control for results that showed up in the first query not to show in the second and so forth).
Maybe you should try including a fourth column, stating the table it came from, and then order and group by it:
SELECT A,B,C, "query 1" as origin FROM table WHERE field LIKE 'query%'
UNION
SELECT A,B,C, "query 2" as origin FROM table WHERE field LIKE '%query'
UNION
SELECT A,B,C, "query 3" as origin FROM table WHERE field LIKE '%query%'
GROUP BY origin, B ORDER BY origin, B ASC LIMIT 5
Add an additional column with hard-coded values that you will use to sort the overall resultset, like so:
SELECT A,B,C,1 as [order] FROM table WHERE field LIKE 'query%'
UNION
SELECT A,B,C,2 as [order] FROM table WHERE field LIKE '%query'
UNION
SELECT A,B,C,3 as [order] FROM table WHERE field LIKE '%query%'
GROUP BY B ORDER BY [order] ASC, B ASC LIMIT 5
Can you do it as a subselect, something like
SELECT * FROM (
SELECT A,B,C FROM table WHERE field LIKE 'query%'
UNION
SELECT A,B,C FROM table WHERE field LIKE '%query'
UNION
SELECT A,B,C FROM table WHERE field LIKE '%query%'
) ORDER BY B ASC LIMIT 5
SELECT distinct a,b,c FROM (
SELECT A,B,C,1 as o FROM table WHERE field LIKE 'query%'
UNION
SELECT A,B,C,2 as o FROM table WHERE field LIKE '%query'
UNION
SELECT A,B,C,3 as o FROM table WHERE field LIKE '%query%'
)
ORDER BY o ASC LIMIT 5
Would be my way of doing it. I dont know how that scales.
I don't understand the
GROUP BY B ORDER BY B ASC LIMIT 5
Does it apply only to the last SELECT in the union?
Does mysql actually allow you to group by a column and still not do aggregates on the other columns?
EDIT: aaahh. I see that mysql actually does. Its a special version of DISTINCT(b) or something. I wouldnt want to try to be an expert on that area :)
If there isn't a sort that makes sense to order them you desire, don't union the results together - just return 3 separate recordsets, and deal with them accordingly in your data tier.
I eventually (looking at all suggestions) came to this solution, its a bit of a compromise between what I need and time.
SELECT * FROM
(SELECT A, B, C, "1" FROM table WHERE B LIKE 'query%' LIMIT 3
UNION
SELECT A, B, C, "2" FROM table WHERE B LIKE '%query%' LIMIT 5)
AS RS
GROUP BY B
ORDER BY 1 DESC
it delivers 5 results total, sorts from the fourth "column" and gives me what I need; a natural result set (its coming over AJAX), and a wildcard result set following right after.
:)
/mp
There are two varients of UNION.
'UNION' and 'UNION ALL'
In most cases what you really want to say is UNION ALL as it does not do duplicate elimination (Think SELECT DISTINCT) between sets which can result in quite a bit of savings in terms of execution time.
Others have suggested multiple result sets which is a workable solution however I would caution against this in time sensitive applications or applications connected over WANs as doing so can result in significantly more round trips on the wire between server and client.
I don't understand why the need of union for taking the data from single table
SELECT A, B, C
FROM table
WHERE field LIKE 'query%'
OR field LIKE '%query'
OR field LIKE '%query%'
GROUP BY B
ORDER BY B ASC LIMIT 5