How to select two different datasets with MySQL - mysql

I am trying to select two data sets from the same table, instead of doing two queries I am trying to select them both in one call.
First of all I want to:
SELECT COUNT(*) AS `total` FROM `Messages` WHERE `id` = '1';
and the second is:
SELECT COUNT(*) AS `total_read` FROM `Messages` WHERE `id` = '1' AND `read` = '1';
Is there anyway to do this in one query?

SELECT
COUNT(*) total,
SUM(IF(read='1',1,0)) total_read
FROM Messages
WHERE id='1';

Related

MySQL: Taking mulitple IDs returned from one query and passing the value in the "IN" of another query

So let's say that I have a query:
SELECT `id` FROM `tablename`
This will returns some IDs in rows. Now I want to use these IDs to get data from another table with the 'IN' function.
SELECT `somecol` FROM `anothertable` WHERE `parent` IN ( {IDs here} )
I could do this with PHP using 2 different queries. But I wanted to know how or can it be done with MySQL alone, using only one query?
Use exists:
SELECT somecol
FROM anothertable a
WHERE EXISTS (
SELECT * FROM tablename t WHERE t.ID = a.parent
);
Just pass in your first query inside you second query:
SELECT
`somecol`
FROM
`anothertable`
WHERE
`parent`
IN (SELECT `id` FROM `tablename`)

MySQL: Combine a subselect and array into one IN statment

I'm not sure if this is possible but what I like to do is the following:
I have a list of id's stored in a table
I have a list of numbers I have already
I want 1 in statement that joins the 2 eg,
SELCET * from `table1` where `ID` IN ( (SELECT `id` from `table2` where `columnA` = 'yes') or (1,2,3,4))
but I am not sure how I can combine the two results in one statement.
The easiest way would probably be to have two separate in conditions:
SELCET *
FROM `table1`
WHERE `id` IN (SELECT `id` FROM `table2` WHERE `columnA` = 'yes') OR
`id` IN (1,2,3,4)

Wrong MySQL subquery count comparison result

So I found a bug in my application, it wasn't showing me a result it should have. I traced it back to the following SQL query (I removed the irrelevant parts).
As you can see the query selects rows from wc_hncat_products of which the corresponding id's have a count of >= 1 inside the wc_hncat_product_category_has_product table
If I execute the query with the subquery result as a column, you can see the result is 1. But when I use it in the WHERE clause the >= 1 comparison fails.
Proof that the subquery DOES return 1:
SELECT `wc_hncat_products`.`id`,
(SELECT Count(*)
FROM `wc_hncat_product_categories`
INNER JOIN `wc_hncat_product_category_has_product`
ON `wc_hncat_product_categories`.`id` =
`wc_hncat_product_category_has_product`.`category_id`
WHERE `wc_hncat_product_category_has_product`.`product_id` =
`wc_hncat_products`.`id`
AND `category_id` IN ( '1' )) count
FROM `wc_hncat_products`
WHERE `id` IN ( '785' )
This query returns one row, with the column count value being 1
No results with subquery count comparison in WHERE clause
SELECT `wc_hncat_products`.`id`
FROM `wc_hncat_products`
WHERE (SELECT Count(*)
FROM `wc_hncat_product_categories`
INNER JOIN `wc_hncat_product_category_has_product`
ON `wc_hncat_product_categories`.`id` =
`wc_hncat_product_category_has_product`.`category_id`
WHERE `wc_hncat_product_category_has_product`.`product_id` =
`wc_hncat_products`.`id`
AND `category_id` IN ( '1' )) >= 1
AND `id` IN ( '785' )
This query selects 0 rows..
How is this possible? You can see the count actually is 1, but the comparison still fails as no results are being returned while the subqueries are identical in both scenarios.
The standard way to implement that type of check is to use EXISTS.
Something like this should work for you:
SELECT `wc_hncat_products`.`id`
FROM `wc_hncat_products`
WHERE EXISTS (SELECT NULL
FROM `wc_hncat_product_categories`
INNER JOIN `wc_hncat_product_category_has_product`
ON `wc_hncat_product_categories`.`id` =
`wc_hncat_product_category_has_product`.`category_id`
WHERE `wc_hncat_product_category_has_product`.`product_id` =
`wc_hncat_products`.`id`
AND `category_id` IN ( '1' ))
AND `id` IN ( '785' )

How to get data from two tables from database?

Can you explain me, why this code not working?
SELECT SUM(`cash`) AS `cash`,COUNT(*) AS `rows` FROM `table_1` WHERE `login` = 'test' UNION ALL SELECT COUNT(*) AS `rows2` FROM `table_2` WHERE `login` = 'test';
In phpMyadmin I see this message:
1222 - The used SELECT statements have a different number of columns
And I could not solve this problem.
A UNION takes the results of multiple SELECT statements and presents them as a single result set. But in order to do this, the number of columns in the individual SELECT statements has to be the same.
To understand this, it may help to format the query a bit:
SELECT
SUM(`cash`) AS `cash`,
COUNT(*) AS `rows`
FROM `table_1`
WHERE `login` = 'test'
UNION ALL
SELECT
COUNT(*) AS `rows2`
FROM `table_2`
WHERE `login` = 'test'
Your first query is selecting two columns, cash and rows. The second query only selects one column, rows2. Also note that since UNION is concatenating the results, you may as well call the corresponding columns in each query by the same name.
If you really don't have any values that you want to select from the second table, you can substitute a default value for the missing columns:
SELECT
SUM(`cash`) AS `cash`,
COUNT(*) AS `rows`
FROM `table_1`
WHERE `login` = 'test'
UNION ALL
SELECT
NULL AS `cash`
COUNT(*) AS `rows`
FROM `table_2`
WHERE `login` = 'test'

merging two SELECT queries

I am either getting old or the queries that I need to write are getting more and more complicated. The following query will get all the tasks associated with the user.
"SELECT `date`
FROM `tasks`
WHERE `user_id`= 1;"
The tasks table is (id, date, user_id, url_id);
Now, I need to get as well records that url_id associates with the user trough the
`urls` table (`id`, `user_id`)
The standalone query would look like this:
"SELECT `t1`.`data`
FROM `tasks` `t1`
JOIN `urls` `u1` ON `u1`.`id` = `t1`.`url_id`
WHERE `u1`.user_id` = 1;"
Though, is it possible to merge these two queries into a single query? My logic says it should be, though I don't see how to do the actual JOIN.
I'd probably use a UNION.
SELECT `date`
FROM `tasks` WHERE `user_id`=1
UNION
SELECT `t1`.`date`
FROM `tasks` `t1`
INNER JOIN `urls` `u1` ON `u1`.`id` = `t1`.`url_id`
WHERE `u1`.user_id`=1;
You can do this in a single query:
SELECT t.date
FROM TASKS t
WHERE t.user_id = 1
OR EXISTS(SELECT NULL
FROM URLS u
WHERE u.id = t.url_id
AND u.user_id = 1)
However, OR is a notoriously bad performer -- it splinters the execution plan. Splitting the query, joining the result sets can be done using the UNION or UNION ALL operators. UNION removes duplicates from the final result set; UNION ALL does not remove duplicates and is faster for it.
SELECT t.date
FROM TASKS t
WHERE t.user_id = 1
UNION ALL
SELECT t.date
FROM TASKS t
WHERE EXISTS(SELECT NULL
FROM URLS u
WHERE u.id = t.url_id
AND u.user_id = 1)
Know your data, so you know which UNION operator best serves your needs.