Performance compare, get concat string by subquery or join table? - mysql

I have a query need to get more then one field from another table, which one of the following will be faster?
1
SELECT *, (SELECT CONCAT(fieldA,'|',fieldB) FROM tableB WHERE bid=id) as moreField FROM tableA
2
SELECT tableA.*, tableB.fieldA, tableB.fieldB FROM tableA INNER JOIN tableB ON bid=id
Actually, I need fieldA and fieldB as separated values, so in case one I will use explode('|',moreField) in PHP to get them separated after the query. Just want to know which query will be faster.

In my experience, nested queries are slow.
If you need concatened results You could do :
SELECT tableA.*, tableB.fieldA, tableB.fieldB, CONCAT(tableB.fieldA,'|',tableB.fieldB) as moreField
FROM tableA INNER JOIN tableB ON bid=id
But you say that you actually need separated values so just use your second solution.

Related

MySQL: Trouble trying to get my SQL statement to work when condition is true but can also accept false

I have the following statement:
SELECT tableA.*, tableB.* FROM tableA, tableB WHERE tableA.userUUID = ? AND tableB.uuid=tableA.tableBUUID
So when a record in table A has a valid tableBUUID and the tableBUUID exists in tableB then the query runs file. But when I removed the tableBUUID from table B without removing it from the record in tableA then the query returns nothing (Which is obviously expected)
I am wondering how I can change the query so that even if the tableBUUID does not match anything, the query will still return what it can even if its nothing/ blank columns from tableB?
Thanks all
You can achieve this via a LEFT JOIN:
SELECT tableA.*, tableB.*
FROM tableA
LEFT JOIN tableB ON tableB.uuid = tableA.tableBUUID
WHERE tableA.userUUID = ?
Fiddle.
Performing a LEFT JOIN will return data from tableA and matching records from tableB if it exists in tableB, otherwise it'll return only the records from tableA.
In the syntax you posted above in your question, you're essentially doing a INNER JOIN by comma separating your tables. This is the old syntax, moving forward you should explicitly write INNER JOIN like so:
SELECT * FROM tableA a INNER JOIN tableB b ON a.column_key = b.column_key
Read more about it in the following previous question:
What's the difference between comma separated joins and join on syntax in MySQL?

MySQL performance comparison between joining table and derived table

I have this two queries following and noticed they have a huge performance difference
Query1
SELECT count(distinct b.id) FROM tableA as a
LEFT JOIN tableB as b on a.id = b.aId
GROUP BY a.id
Query2
SELECT count(distinct b.id) FROM tableA as a
LEFT JOIN (SELECT * FROM tableB) as b on a.id = b.aId
GROUP BY a.id
the queries are basically joining one table to another and I noticed that Query1 takes about 80ms whereas Query2 takes about 2sec with thousands of data in my system. Could anyone explain me why this happens ? and if it's a wise choice to use only Query2 style whenever I am forced to use it ? or is there a better way to do the same thing but better than Query2 ?
When you replace tableB with (SELECT * FROM tableB) you are forcing the query engine to materialize a subquery, or intermediate table result. In other words, in the second query, you aren't actually joining directly to tableB, you are joining to some intermediate table. As a result of this, any indices which might have existed on tableB to make the query faster would not be available. Based on your current example, I see no reason to use the second version.
Under certain conditions you might be forced to use the second version though. For example, if you needed to transform tableB in some way, you might need a subquery to do that.

How to do a join on 2 tables, but only return the data for one table?

I am not sure if this is possible. But is it possible to do a join on 2 tables, but return the data for only one of the tables. I want to join the two tables based on a condition, but I only want the data for one of the tables. Is this possible with SQL, if so how? After reading the docs, it seems that when you do a join you get the data for both tables. Thanks for any help!
You get data from both tables because join is based on "Cartesian Product" + "Selection". But after the join, you can do a "Projection" with desired columns.
SQL has an easy syntax for this:
Select t1.* --taking data just from one table
from one_table t1
inner join other_table t2
on t1.pk = t2.fk
You can chose the table through the alias: t1.* or t2.*. The symbol * means "all fields".
Also you can include where clause, order by or other join types like outer join or cross join.
A typical SQL query has multiple clauses.
The SELECT clause mentions the columns you want in your result set.
The FROM clause, which includes JOIN operations, mentions the tables from which you want to retrieve those columns.
The WHERE clause filters the result set.
The ORDER BY clause specifies the order in which the rows in your result set are presented.
There are a few other clauses like GROUP BY and LIMIT. You can read about those.
To do what you ask, select the columns you want, then mention the tables you want. Something like this.
SELECT t1.id, t1.name, t1.address
FROM t1
JOIN t2 ON t2.t1_id = t1.id
This gives you data from t1 from rows that match t2.
Pro tip: Avoid the use of SELECT *. Instead, mention the columns you want.
This would typically be done using exists (or in) if you prefer:
select t1.*
from table1 t1
where exists (select 1 from table2 t2 on t2.x = t1.y);
Although you can use join, it runs the risk of multiplying the number of rows in the result set -- if there are duplicate matches in table2. There is no danger of such duplicates using exists (or in). I also find the logic to be more natural.
If you join on 2 tables.
You can use SELECT to select the data you want
If you want to get a table of data, you can do this,just select one table date
SELECT b.title
FROM blog b
JOIN type t ON b.type_id=t.id;
If you want to get the data from two tables, you can do this,select two table date.
SELECT b.title,t.type_name
FROM blog b
JOIN type t ON b.type_id=t.id;

Regarding select query in the column

Want to have the multiple columns returned from select query in the column of the main select query. Getting MySQL error. How can I do it?
SELECT test.val1,
(SELECT
cc.id, cc.nbr,cc.addr
FROM
(
Select temptable.id ,temptable.nbr,temptable.addr
from temptable
inner join temptable2 on temptable2.id=temptable.id
) cc),
test.val2,
test.val3
FROM test
innerjoin test2 on test.id=test2.id
A subquery in the select list has to return 1 field and 1 record. If you want values from multiple fields to appear in a single column, then you can use concat() or concat_ws() mysql functions to concatenate them into a single field. If you want to combine multiple fields and multiple rows into one field, then above the afore mentioned 2 functions you will need group_concat().
select concat_ws(';',field1, field2) from table
However, I think in this particular case you may want to place the subquery into the from clause and reference the columns from there in the select clause.
Please try the below if the four tables are related.
select tb1.tb_id, tb1.val1, tb2.tb_id from (select test.id as tb_id, val1, val2, val3 from test inner join test2 on test.id=test2.id) as tb1 join (select temptable.id as tb_id from temptable join temptable2 on temptable.id=temptable2.id) as tb2 on tb2.tb_id=tb1.tb_id;

Selecting from two tables, with different columns, where one needs a count

I have two tables, TableA and TableB.
I need to select one count value from TableA, based on a where condition.
I need to select two values from TableB.
I'd like all the values in one result set. There will never be more than one row in the result set.
Here's what I have now:
SELECT count(id) FROM TableA WHERE ($some_where_statement) SELECT owner, owner_ID from TableB
I know this should be simple, but this is throwing an error. Any suggestions?
You can cross join to join rows from two unrelated tables:
SELECT T1.cnt, T2.owner, T2.owner_ID
FROM (SELECT count(id) FROM TableA WHERE ($some_where_statement)) AS T1
CROSS JOIN (SELECT owner, owner_ID from TableB) AS T2
To have only one row in the result set, it is assumed that both subqueries only return one row. I suspect that this is not the case for the second subquery. You are probably missing a where clause.