MySQL referencing nested query result in the SELECT? - mysql

Say you have two tables with columns:
table1: id, data
table2: id, t1_ref (which is a FK to table1), some_other_column
Now I can write something like (I know that this can be written differently, more efficient, etc, not looking for those):
SELECT t1.data,
(SELECT count(*)
FROM table2 t2
WHERE t2.t1_ref = t1.id) AS nested_result
FROM table1 t1;
My question is, where can I use 'nested_result' in the rest of the main query? Can I use it in the FROM (in another nested select for instance)? Or in the WHERE? Or in a GROUP BY? Or on a ORDER BY? Anywhere else?
For example MySQL doesn't seem to like:
SELECT t1.data,
(SELECT count(*)
FROM table2 t2
WHERE t2.t1_ref = t1.id) AS nested_result
FROM table1 t1
WHERE nested_result > 100;
but what are the general rules here?

nested_result is a column alias.
You can use it in the group by, having, and order by clauses.
You can put this whole statement in a subquery, and use it in the outer query.
Here is the reference in the documentation:
The following list provides additional information about other SELECT
clauses:
A select_expr can be given an alias using AS alias_name. The alias is
used as the expression's column name and can be used in GROUP BY,
ORDER BY, or HAVING clauses. For example:
SELECT CONCAT(last_name,', ',first_name) AS full_name
FROM mytable
ORDER BY full_name;
EDIT:
For your particular example, you can change the where to having:
SELECT t1.data,
(SELECT count(*)
FROM table2 t2
WHERE t2.t1_ref = t1.id
) AS nested_result
FROM table1 t1
HAVING nested_result > 100;
This is a MySQL extensions and doesn't work in other databases. As much as I don't like it, I have to admit that it is convenient.

Related

Create a new variable in SQL by groupby

I have 2 sql table as follows:
First table t1:
Second table t2:
I need to calculate the count of "Number" column based on "Name" column from t1 and merge it with t2.
I wrote following code. But it seems not working
select *
from (
select Name, count(Number) as count
from t1
group by Name ) as a
join ( select *
from t2 ) as b
on a.Name = b.Name;
Can any one figure out what is wrong ? Thank you very much
I think you want to use SUM() instead of COUNT().
Because SUM() sums some integers, while COUNT() counts number of occurencies.
And as also stated in the comments, multiple columns with same names will create conflicts, so you have to select the wanted columns explicit (that is usually a good idea anyway).
You could obtain your wanted endgoal by this query:
select
SUM(Number),
t1.Name,
(select val1 FROM t2 WHERE t2.Name = t1.Name LIMIT 1) as val1
FROM t1
GROUP BY t1.Name
Example in sqlfiddle: http://sqlfiddle.com/#!9/04dddf/7

How to use CONCAT_WS/GROUP_CONCAT in LIKE Mysql?

I am trying to execute below query which says
SELECT t1.name from table t1, t2 WHERE t2.data LIKE(CONCAT_WS(',' DISTINCT(t1.name)))
OR
SELECT t1.name from table t1, t2 WHERE t2.data LIKE(GROUP_CONCAT(DISTINCT(t1.name) SEPARATOR ','))
Both ways say
#1111 - Invalid use of group function
Well not totally sure what trying to do, but suspect will need a subquery to join on an aggregate function.
SELECT names
FROM t2
INNER JOIN (SELECT GROUP_CONCAT(DISTINCT name SEPARATOR ',') as names
FROM t1
GROUP BY user_id) t1 USING t2.data = names
That query still doesnt really make sence, but might show roughly how to construct it.
As comments say, really need more context to under WHAT you trying to do.

Rule to put fields in select clause when joining multiple tables and query has group by clause

I am learning sql join and would like to clear an idea.
I understand that all the select columns should present in group by clause.
For example,
select a, b
from table_one
group by a,b;
I want to join two tables, something similar to this -
select table_one.a
from table_one, table_two
where table_one.id = table_two.id
group by table_two.c
The question is - should I put table_two.c in select since it is in group by clause?
A group by clause is neede, if you have an analytical function. Simple example:
select order_date, sum(orders)
from orders_table
group by order_date;
It makes logically sense, to group only on columns, that are also in your select clause. Otherwise, you could have weird data for the end user. Example:
select order_date, sum(orders)
from orders
group by country. order_date;
This would give you a separate row for each date and country, but you only see the date in the result.
So the simple rule ist: add all columns to the group by statement that do not use an analytical function (i.e. min(), max(), avg(), count()) and do not use columns in the group by statement that are not also present in the select clause.
This does not change when joining. Grouping is completely independant from joins. THe only thing that matters is, which columns you use.
When joining tables you can use the JOIN-statements instead
Example with your query:
SELECT t1.a
FROM table_one t1 /*(t1 is the alias for the table)*/
INNER JOIN table_two t2 ON t1.id = t2.id
GROUP BY t2.c
You don't need to put the t2.c in your select, if you don't specifically want it in the results. Since you are only selecting t1.a, that is all you're gonna get.
Another answer here on SO regarding GROUP BY is worth reading aswell. :)
https://stackoverflow.com/a/1591976/1025823

use matched argument from IN() function

im using the IN() function to match againts some ids.
SELECT * FROM my_table WHERE id IN(id1,id2,id3)
the thing is, now i need to calculate a SUM() based on the matched id, and i would like to do it on the same query. Something like
SELECT *,(SELECT SUM() WHERE id = the_matched_id) FROM my_table WHERE id IN(id1,id2,id3)
¿is it possible? maybe i should consider to change my query, or do it separately. ¿ What a do you suggest?
Thanks!
The matched ID is just the ID of each row from the outer table. You can use different aliases to compare these IDs.
SELECT *, (SELECT SUM(summableColName) FROM my_table t2 WHERE t2.id = t1.id)
FROM my_table t1 WHERE id IN (id1, id2, id3)
Try something like
SELECT id,sum(field) FROM my_table WHERE id IN(id1,id2,id3)
GROUP BY id

MySQL correlated subquery SUM() ORDER BY

Is there anyway to optimize the following query:
SELECT
t1.id,
(SELECT SUM(col1) FROM table_name_two t2 WHERE t2.name LIKE CONCAT('%',t1.name)) AS col1_count
FROM
table_name_one t1
ORDER BY
col1_count DESC
Using ORDER BY col1_count DESC takes a long time.
Thanks.
Just make a normal join with your comparison in the join's on clause:
SELECT
t1.id,
SUM(t2.col1) AS col1_count
FROM table_name_one t1
LEFT JOIN table_name_two t2 on t2.name LIKE CONCAT('%', t1.name)
GROUP BY 1
ORDER BY 2 DESC
It should be way faster this way - it's basically one query instead of "n" queries, although it won't get any help from indexes using the LIKE operator with a leading %