How do I Concatenate entire result sets in MySQL? - 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

Related

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

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;

MySQL query to join columns and limit each column by a number

MySQL query
SELECT A FROM data WHERE A LIKE '%$term%'
|| B LIKE '%$term%' LIMIT 5
UNION SELECT D FROM data WHERE D LIKE '%$term%'
|| E LIKE '%$term%' LIMIT 5
In this I want to show data of my A column when it matches against data field from column A or B limit this number by 5 + data of my D column when it matches against data field from column D or E limit this number by 5
But in actual it shows only 5 row instead of 10. Any idea where I am wrong. Please Help
You can wrap each of the individual queries (including the LIMIT clause) in parens. This allows a LIMIT clause to be applied to each individual query.
For example:
( SELECT A FROM data
WHERE A LIKE '%$term%' || B LIKE '%$term%'
LIMIT 5
)
UNION ALL
( SELECT D FROM data
WHERE D LIKE '%$term%' || E LIKE '%$term%'
LIMIT 5
)
(The only changes from your original query is the addition of the parens around each SELECT, and the use of UNION ALL in place of UNION. If we need to identify and remove duplicate rows, we use the UNION operator, otherwise, we use UNION ALL.
If you need the resultset in a particular order, add an ORDER BY clause at the end of the statement, following the last close paren.
Union removes any of duplicate data while fetching the data so if above query contains records A and if below one contain a record A , in final result there will be only one records for both of them. so use UNION ALL here.
(SELECT A FROM data WHERE A LIKE '%$term%' ||
B LIKE '%$term%' LIMIT 5)
UNION ALL
(SELECT D FROM data WHERE
D LIKE '%$term%' || E LIKE '%$term%' LIMIT 5)

order multiple tables according to one column

Is it possible, using SQL to pull data from different tables, then sort the data according to one column that is in all tables. eg, I have 3 tables. Base, Selects, Sub. They all 3 have a position column,
Select base_layers.position, selects.position, subbases.position
from base_layers,selects,subbases
Order By (alls)position;
That is exactly what I actually want to do... But have a feeling it is not possible.
Use a union:
(I'm assuming you don't want to cross join all 3 tables)
select Position
from
(
select base_layers.position AS Position
from base_layers
union
select selects.position
from selects
union
select subbases.position
from subbases
) x
order by Position ASC;
Your syntax was incorrect. Try this version.
SELECT * FROM
(
SELECT base_layers.position
FROM base_layers
UNION ALL
SELECT selects.position
FROM selects
UNION ALL
SELECT subbases.position
FROM subbases
) tbl ORDER BY tbl.position;

mysql union statement with order by

I'am trying to understand what causes the following, maybe you could help me:
I have a query like:
select field1,fieldDate from table1
union all
select field1,fieldDate from table2
order by fieldDate desc
and the another one like this:
select field1,field2,fieldDate from table1
union all
select field1,field2,fieldDate from table2
order by fieldDate desc
So basically they are the same with the exception that in the second I retrieve an extra field.
Now, both results come with a diferent ordering, but just for the cases that the dates are exacly the same. For example there are 2 rows (row1,row2) with date 2009-11-25 09:41:55. For query 1 row1 comes before row2 and for query 2 row2 comes before row1.
Does somebody knows why this happens?
Thanks,
Regards
The ordering based on any fields that you don't explicitly order by is undefined, and the optimizer can change the ordering if it thinks that results in a better execution plan. Given two rows with the exact same value in the order by field you can not depend on them being in any particularly order in relation to each other unless you explicitly order by another field with different values.
Can you do this
select * from ( select
field1,field2,fieldDate, 0 as ordercol from table1
union all select
field1,field2,fieldDate, 1 as ordercol from table2) t1
order by fieldDate desc, ordercol asc
Straight from the MySQl manual, to user order by on a union you have to parenthesis the individual tables.
(select field1,fieldDate from table1)
union all
(select field1,fieldDate from table2)
order by fieldDate desc
This is not SQL standards compliant! The code you entered should order the union of both tables but to my surprise MySQL has the above syntax.
The order in which rows with the same fieldDate are returned can differ for each query execution. Usually this order will be the same but you should not count on it. If you want any extra ordering state more order by fields.
EDIT: This answer is wrong: the order by works on the entire union. I'll leave it here to save others the trouble :)
Your order by only works on the second part of the union. You can use a subquery to make the order by work on the entire union:
select field1,field2,fieldDate
from (
select field1,field2,fieldDate
from table1
union all
select field1,field2,fieldDate
from table2
) SubQueryName
order by fieldDate desc

Selecting from multiple MySQL tables

I have a few tables that have similar fields but not exactly the same.
The same fields they have are description (text field) and modified (unixtime)
I would like to select the last modified items from these tables based on unixtime. I cant use UNION since the tables aren't the same and the multiple table select times out.
I've been trying to look for this but no luck, either people are using JOINS or SELECT A., B. FROM table A, table B
How different they are?
Maybe you can get the common fields out:
select t1.name1 as name from table1
union
select t2.name2 as name from table2
Try this:
SELECT
IF (A.modified > B.modified, A.modified, B.modified) AS modified,
IF (A.modified > B.modified, A.description, B.description) AS description,
FROM
(SELECT description, modified FROM A ORDER BY modified DESC LIMIT 1) AS A,
(SELECT description, modified FROM B ORDER BY modified DESC LIMIT 1) AS B
LIMIT 1
However, it's pretty much the same as just doing two queries (only more complicated) so I wouldn't recommend it.
Try adding desc index on 'modified' if your select timesou, and use limit on select to return just one (last) row.
Then you can:
SELECT
A,B,C,D, desc, modified
FROM
TABLEA
UNION ALL
SELECT
CAST(E as <A type>), CAST(F AS <B type>) ..., desc, modified
FROM
TABLE B