Joining on derived column without using subquery - mysql

In MySQL I'm trying to join two tables on a derived column, something like this:
SELECT C.country,
IFNULL(C.preferred_city, C.default_city) AS best_city,
PC.postal_code
FROM Countries as C
INNER JOIN PostalCodes AS PC
ON best_city=PC.city
This of course does not work because best_city is outside the scope of the ON clause.
The only solution I could find was using a subquery (or is this considered a derived table? I'm fuzzy on the nomenclature):
SELECT BC.*, PC.postal_code
FROM (
SELECT country, IFNULL(preferred_city, default_city) AS best_city
FROM COUNTRIES
) AS BC
INNER JOIN PostalCodes AS PC
ON BC.best_city=PC.city
which works nicely from the shell. However, I'm trying to implement this as a view and it gives me the error: ERROR 1349: View's SELECT contains a subquery in the FROM clause
How can I rework this to join without using a subquery??
Thanks!

Try something like:
SELECT BC.*, PC.postal_code
FROM COUNTRIES BC
INNER JOIN PostalCodes AS PC
ON PC.city = IFNULL(preferred_city, default_city)

Related

What is the difference between JOIN and simple SELECT in MySQL?

I have two mySQL statements. First is:
SELECT o.OrderID, c.CustomerName, o.OrderDate
FROM Customers AS c, Orders AS o
WHERE c.CustomerID=o.CustomerID;
The second is:
SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate
FROM Orders
INNER JOIN Customers
ON Orders.CustomerID=Customers.CustomerID;
Both produce the same result, but second doesn't contain reference on Customers table in FROM request.
My question is - what is the difference between these two sql statements? In which cases should I use JOIN and in which cases should I use simple SELECT from two tables?
They are the same except the second is easier to read, so you should use that one.
Those JOIN are different, although the result are the same.
The First one is CROSS JOIN and adds the condition in where, which is implicit CROSS JOIN
The second one is INNER JOIN
If you want to connect two tables I would use INNER JOIN instead of CROSS JOIN Because the intention of the inner join table is clearer

MySQL --- Explicit INNER JOIN with selection from multiple tables

Whenever I have a need to do an inner join where I have to select columns from multiple tables, I have got the syntax working correctly with implicit joins, without any difficulty. However, I have struggled to get it working with explicit inner joins.
Let me illustrate with an example from the MySQL World Database
My illustrative query, using implicit inner join, is as follows:
SELECT Name, Language, Percentage
FROM Country, CountryLanguage WHERE Code = CountryCode ;
This works as expected. I can have the columns in any order, from either table, without any issues.
I would like to have the explicit INNER JOIN version of the above query (using "INNER JOIN" and "ON").
You can simply replace the , in your implicit join with the word JOIN:
SELECT Name, Language, Percentage
FROM Country
JOIN CountryLanguage
WHERE Code = CountryCode
and the query will work fine. You can also replace WHERE with ON and again it will work fine. Finally if you want to explicitly name the tables where the columns come from (and this is the preferred approach), you would use:
SELECT c.Name, cl.Language, cl.Percentage
FROM Country c
JOIN CountryLanguage cl
ON c.Code = cl.CountryCode
Maybe it would be like
SELECT Name, Language, Percentage,
FROM Country
INNER JOIN CountryLanguage ON Country.Code = CountryLanguage.CountryCode

sql , two USING clauses in one statement

im just doing some sql exercises on w3 and wondering about the following statement
SELECT a.ord_no, a.purch_amt, b.cust_name, c.name,
FROM orders a
INNER JOIN customer b USING (customer_id)
INNER JOIN salesman c USING (salesman_id)
edit: i posted wrong testing results , statement doesnt work for reasons explained by answer from ScaisEdge.
Looking to your code
FROM orders a
INNER JOIN customer b USING (customer_id)
INNER JOIN salesman c USING (salesman_id)
seems that the using clause is ambigous when you use more then 2 tables
In your case the second using is for customer or orders .. ??
The sql engine can't define the correct one so you must use explicit on clause for avoid using ambiguity

SELECT * Within a join

Is it possible to use *when using JOIN. I so far have the following result using
SELECT * FROM default_ps_products_categories INNER JOIN default_ps_products_brand_by_cat
but I am wanting it to return one of each and not two as shown - Do I have to do the query correctly and select the tables?. The two coloumns that match are id and cat_id
You're missing the ON clause in the join, in which case MySQL returns a full Cartesian join instead of complaining.
Try (I'm using aliases because the table names are long):
SELECT *
FROM default_ps_products_categories C
INNER JOIN default_ps_products_brand_by_cat B ON C.id = B.cat_id
Note: The * is fine and is not the source of your problem.

What would cause a query to run slowly when used a subquery, but not when run separately?

I have something similar to the following:
SELECT c.id
FROM contact AS c
WHERE c.id IN (SELECT s.contact_id
FROM sub_table AS s
LEFT JOIN contact_sub AS c2 ON (s.id = c2.sub_field)
WHERE c2.phone LIKE '535%')
ORDER BY c.name
The problem is that the query takes a very very very long time (>2minutes), but if I take the subquery, run it separately, implode the ids and insert them into the main query, it runs in well less than 1 second, including the data retrival and implosion.
I have checked the explains on both methods and keys are being used appropriately and the same ways. The subquery doesn't return more than 200 IDs.
What could be causing the subquery method to take so much longer?
BTW, I know the query above can be written with joins, but the query I have can't be--this is just a simplified version.
Using MySQL 5.0.22.
Sounds suspiciously like MySQL bug #32665: Query with dependent subquery is too slow.
What happens if you try it like this?
SELECT c.id
FROM contact AS c
INNER JOIN (SELECT s.contact_id
FROM sub_table AS s
LEFT JOIN contact_sub AS c2 ON (s.id = c2.sub_field)
WHERE c2.phone LIKE '535%') subq ON subq.contact_id=c.id
ORDER BY c.name
Assuming that the result of s.contact_id is unique. You can add distinct to the subquery if it is not.
I always use uncorrelated subqueries this way rather than using the IN operator in the where clause.
Have you checked the Execution Plan for the query? This will usually show you the problem.
Can't you do another join instead of a subquery?
SELECT c.id
FROM contact AS c
JOIN sub_table AS s on c.id = s.contact_id
LEFT JOIN contact_sub AS cs ON (s.id = cs.sub_field)
WHERE cs.phone LIKE '535%'
ORDER BY c.name
Since the subquery is referring to a field sub_field in the outer select, it has to be run once for each row in the outer table - the results for the inner query will change with each row in the outer table.
It's a correlated subquery. It runs once for each row in the outer select. (I think. You have two tables with the same correlation name, I'm assuming that's a typo. That you say it can't be rewritten as a join means it's correlated. )
Ok, I'm going to give you something to try. You say that the subquery is not correlated, and that you still can't join on it. And that it you take the output of the subquery, and lexically substitute that for the subquery, the main query runs much faster.
So try this: make the subquery into a view: create view foo followed by the text of the subquery. Then rewrite the main query to get rid of the "IN" clause and instead join to the view.
How's the timing on that?