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

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)

Related

MySQLi query only one type of result

I am trying to query all the results for only one type of message from the database:
Table:
ID List Content
1 8 This
2 8 That
3 9 Other
4 8 Last
There will be about 20,000 rows in this table, so I don't want to select them all and then sort through them if I don't have to. Basically, the List numbers will be changing, so I won't know what they are, but I only want to query results where List is the same.
It's a cron job script that will be removing these from the table after it's ran, so it doesn't matter what the List is, as long as each query returns all the same List.
What's the way of doing this straight from the MySQLi query without knowing what List is?
SELECT * FROM Table WHERE List = 8
You seem to want to select rows where list is duplicated. To get the rows with the most duplication, you can use:
select t.*
from table t join
(select list, count(*) as cnt
from table
group by list
order by count(*) desc
limit 1
) tt
on t.list = tt.list;
If you want any rows where list is duplicated, you can remove the having clause.
Here's a way using exists to select all rows where another row with the same List value exists.
select * from mytable a
where exists (
select 1 from mytable b
where b.List = a.List
and b.Id <> a.Id
)

mysql union getting 2 column names from another table corresponding to 2 id columns

I have a table "task" which stores the details of a task that is created, I need to get the names of the creator ID and the ASSIGNEDTO ID in a single query for which i created a UNION however I get the following error in mysql
Both the select queries execute perfectly as individual queries
#1222 - The used SELECT statements have a different number of columns
SELECT a.task_id, a.task_title,a.task_created_by,a.task_creation_date,b.user_id, b.user_email FROM task a,users b WHERE a.task_created_by = b.user_id
UNION
SELECT a.task_assigned_to, b.user_email FROM task a,users b WHERE a.task_assigned_to = b.user_id
Only selects based on same columns can be subjects to UNION
There's a workaround that implies using "as" for any column that you might not have in the other table. Like this:
SELECT b, '' as c FROM table1
UNION ALL
SELECT b, c FROM table2
Based on this the "c" for table1 will always be empty, but the UNION will still work.
Use this logic to UNION tables that have different columns

MySQL query with 2 SELECTs, UNION and LIMIT - how to count all items?

I can't figure out how to count results from my query because I limit the output:
(SELECT "new" as type, name FROM newUsers WHERE name LIKE '%John%')
UNION
(SELECT "old" as type, name FROM oldUsers WHERE name LIKE '%John%')
ORDER BY 1 ASC LIMIT 1, 10
The farthest I got was to do SELECT COUNT(*) ( my query ) as userCount but then I don't get all other fields that were outputted by my query.
( select SQL_CALC_FOUND_ROWS ...)
union
( select ...) // not using SQL_CALC_FOUND_ROWS here
order by ... limit ...;
After getting result from the first query,
you can query again
select found_rows(); // to get all the rows count
The info from documentation
This would probably answer the letter of what you seem to be asking for, but isn't a very sensible way to formulate the query:
SELECT c.numusers, n.type, n.name
FROM (SELECT "new" AS type, name FROM newUsers WHERE name LIKE '%John%') AS n
JOIN (SELECT COUNT(*) AS numusers FROM newUsers WHERE name LIKE '%John%') AS c
UNION
SELECT c.numusers, o.type, o.name
FROM (SELECT "old" AS type, name FROM oldUsers WHERE name LIKE '%John%') AS o
JOIN (SELECT COUNT(*) AS numusers FROM oldUsers WHERE name LIKE '%John%') AS c
ORDER BY 1 ASC LIMIT 1, 10
The only oddity here is that there is no join condition (neither an ON nor a USING clause) between the two tables. You might need to use a CROSS JOIN instead of an (INNER) JOIN; alternatively, you can introduce a column "new" AS type to the count query, and join ON n.type = c.type. You might then need to add a GROUP BY clause - in most DBMS you would need it, but MySQL may let you get away without it.
However, I think you would do better with two separate queries - one for the type and name as in your question, and the other as:
SELECT COUNT(*) AS numusers, "new" AS type
FROM newUsers
WHERE name LIKE '%John%'
GROUP BY type
UNION
SELECT COUNT(*) AS numusers, "old" AS type
FROM oldUsers
WHERE name LIKE '%John%'
GROUP BY type;
Given that you are using MySQL, you may be able to get away without the GROUP BY clauses in the second query.

MySQL Query: How to select rows that don't have a certain value?

I am having trouble writing a query and I don't even know if it is possible. Take this table for example:
id group active
1 A NO
2 A YES
3 A NO
4 B YES
5 B NO
6 C NO
7 C NO
Table above is just an example. In real table there are much more columns the those tree so have that in mind. What I need is a way to select only group names that don't have any active row. In this case both "A" and "B" groups have at least one row with "active" = "YES" but if you look at C there are no active rows. The only thing I would need as a result is a group column value (in this case "C") not entire row.
Is this possible?
SELECT DISTINCT group FROM table WHERE group NOT IN
(SELECT DISTINCT group FROM table WHERE active = 'YES')
You first want to get all the groups you wish to exclude, and then use the NOT IN clause to return all the other groups not in that list.
SELECT DISTINCT t.group
FROM table t
WHERE t.group NOT IN
(SELECT DISTINCT t.group
FROM table t
WHERE t.active='YES');

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