mysql SELECT FROM two tables and LEFT JOIN - mysql

I have problem with select from two tables and left join to third. Query:
SELECT
c.id AS currency, u.user, us.enabled AS currency
FROM
users AS u,
currency AS c
LEFT JOIN users_settings AS us ON(c.id=us.currency, u.user=us.user)
WHERE
c.off=0 AND c.disabled=0 AND c.status=1
Error:
#1054 - Unknown column 'u.user' in 'field list'
I need Cartesian product of users and currency.
Users: id, login, email, pass
http://en.wikipedia.org/wiki/Cartesian_product

You are mixing explicit and implicit join syntax. Try this:
SELECT c.id AS currency, u.user, us.enabled AS currency
FROM currency AS c LEFT JOIN
users_settings AS us
ON c.id = us.currency LEFT JOIN
users u
on u.user = us.user
WHERE c.off = 0 AND c.disabled = 0 AND c.status = 1 ;
MySQL does not necessarily allow the fields to be known over a ,. Scoping is one of the differences between , and cross join. In any case, though, you should use a separate on clause for each join.
Here is the description in the documentation:
INNER JOIN and , (comma) are semantically equivalent in the absence of
a join condition: both produce a Cartesian product between the
specified tables (that is, each and every row in the first table is
joined to each and every row in the second table).
However, the precedence of the comma operator is less than of INNER
JOIN, CROSS JOIN, LEFT JOIN, and so on. If you mix comma joins with
the other join types when there is a join condition, an error of the
form Unknown column 'col_name' in 'on clause' may occur. Information
about dealing with this problem is given later in this section.
Instead of trying to really understand what this means, just avoid using , in the from clause. It is not ever needed.

Related

How to do multiple joins when some tables are empty

I am trying to append 'lookup data' to a main record text/description field so it looks something like this:
This is the Description Text
LookUpName1:
LookupValue1
LookupValueN
This worked fine with Inner Join like so
Select J.id, Concat('<b>LookUpName</b>:<br>',group_concat(F.LookUpValue SEPARATOR '<br>'))
from MainTable J Inner Join
LookUpTable L Inner Join
LookUpValuesTable F
On J.ID = L.JobID and F.ID = L.FilterID
Group by J.ID
However my goal is to add append multiple Lookup Tables and if I add them to this as Inner Joins I naturally just get those record where both/all the LookupTables have records.
On the other hand when I tried Join or Left Join I got an error on the Group by J.ID.
My goal is to append any of the existing Lookup Table values to all of the Description. Right now all I can achieve is returning appended descriptions which have ALL of the Lookup table values.
Your query would work if the on clauses were in the "right" place:
select J.id,
Concat('<b>LookUpName</b>:<br>', group_concat(F.LookUpValue separator '<br>'))
from MainTable J left join
LookUpTable L
on J.ID = L.JobID left join
LookUpValuesTable F
on F.ID = L.FilterID
group by J.ID;
The problem with your query is a MySQL (mis)feature. The on clause is optional for an inner join. Don't ask me why the MySQL designers thought inner join and cross join should be syntactically equivalent. Every other database requires an on clause for an inner join. It is easy enough to express a cross join using on 1=1.
However, the on clause is required for the left join, so when you switch to a left join, the compiler has a problem with the unorthodox syntax. The real problem is a missing on clause; this just happens to show up as "I wasn't expecting a group by yet." Using more traditional syntax with each join followed by an on should fix the problem.

SQL Query not working with joins

First of all the tiny query works but I need to put some joins in the middle of it to make a condition.
The tiny query is the following:
SELECT COUNT(vis.id), country.cod
FROM visits AS vis, countries AS country
WHERE country.description = vis.country
GROUP BY country.cod
The problem now is that I need to add another condition in the where clause, and this condition comes, necessarily from a join in two tables.
SELECT COUNT(vis.id), country.cod
FROM visits AS vis, countries AS country
INNER JOIN products AS prod ON prod.id = vis.id_product
INNER JOIN customers AS cust ON cust.id = prod.id_customer
WHERE country.description = visit.country AND prod.id_customer = 13
GROUP BY country.cod
The error I receive is:
#1054 - Unknown column 'vis.id_product' in 'on clause'
And trust me, that field exists. Also, I've tried, just for testing, to put other fields instead of id_product and the error is the same.
You have given the table visits the alias vis. Now you need to use it.
SELECT COUNT(vis.id), country.cod
FROM visits AS vis JOIN
countries AS country
ON country.description = vis.country JOIN
products AS prod
ON prod.id = vis.id_product JOIN
customers AS cust
ON cust.id = prod.id_customer
WHERE prod.id_customer = 13
GROUP BY country.cod;
In addition, you are mixing implicit and explicit joins. Only use explicit joins, where the join conditions go in the on clause and not in the where clause. A simple rule: Never use commas in the from clause.

My SQL query is returning results but they are repeated ~50 times. I don't understand why

The query I'm using calls on a few tables in the database and works fine. However, when I add line 10 to the mix it returns 50 or more repeated results. I'm still somewhat new to SQL and Sequel Pro so I'm sure the solution isn't too complicated but I am truly stumped right now.
Here is the code:
SELECT c.first_name, c.last_name, ca.company, ca.city, ca.state, ct.certificate_number, ct.certificate_date
FROM customer c, customer_type ctype, cust_address ca, certification ct, cust_prof_cert cp
WHERE ca.id_customer = c.id_customer LIKE cp.prof_cert_id_prof_cert
AND c.customer_type_id_customer_type = ctype.id_customer_type
AND ct.customer_id_customer = c.id_customer
AND ca.id_customer = c.id_customer
AND ctype.customer_type IN('CIRA','CIRA, CDBV')
AND ct.course_type_id_course_type = 1
AND ct.certificate_number IS NOT NULL
AND cp.prof_cert_id_prof_cert = "1"
ORDER BY ct.certificate_number ASC, c.last_name ASC;
Thank you for your time.
By Doing your SQL like that you are not relating the data, just selecting it. I would recommend changing your SQL to use JOINS.
SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate
FROM Orders
INNER JOIN Customers
ON Orders.CustomerID=Customers.CustomerID;
Here is an article that might be able to help you a bit: w3schools, Joins
Here's your query using the SQL92 syntax for joins. You should use this syntax instead of the SQL89 "comma-style" joins.
SELECT c.first_name, c.last_name, ca.company, ca.city, ca.state,
ct.certificate_number, ct.certificate_date
FROM customer AS c
INNER JOIN customer_type AS ctype ON c.customer_type_id_customer_type = ctype.id_customer_type
INNER JOIN cust_address AS ca ON ca.id_customer = c.id_customer
INNER JOIN certification AS ct ON ct.customer_id_customer = c.id_customer
INNER JOIN cust_prof_cert AS cp -- what's this join condition?
WHERE ca.id_customer = c.id_customer LIKE cp.prof_cert_id_prof_cert
AND ctype.customer_type IN('CIRA','CIRA, CDBV')
AND ct.course_type_id_course_type = 1
AND ct.certificate_number IS NOT NULL
AND cp.prof_cert_id_prof_cert = '1'
ORDER BY ct.certificate_number ASC, c.last_name ASC;
A few weird things I notice in this query:
The first term in the WHERE clause is strange. You should know that LIKE has higher precedence than = so this might not be doing what you think it's doing. It's as if you wrote
WHERE ca.id_customer = (c.id_customer LIKE cp.prof_cert_id_prof_cert)
Which means evaluate the LIKE and produce a 0 or a 1 to represent the boolean condition. Then look for a ca.id_customer matching that 0 or 1.
Given that strange term, I can find no other join condition for the cp table. The default join if you give no restriction for it is that every row matches every row in the joined tables. So if you have 50 rows where cp.prof_cert_id_prof_cert = 1, then it will effectively multiply the results from the rest of the joined tables by 50.
This is called a Cartesian product, or in MySQL parlance it's counted in SHOW STATUS as a Full join.
ctype.customer_type IN('CIRA','CIRA, CDBV') You have quoted the second and third strings together. Basically, this means you are trying to match the column against two strings, one of which happens to contain a comma.
You probably meant to write ctype.customer_type IN('CIRA','CIRA','CDBV') so the column may match any of these three values.
I would suggest not querying multiple tables in your FROM clause, I believe this is the cause of your duplicate rows. If you separate out the tables into separate inner or left joins, (whichever you need) you should be able to match which ever keys in each table manually, instead of having SQL attempt to automatically do this.

MySQL - SELECT with LEFT JOIN optimization

I have 3 tables to select from. 2 of them are always necessary (tbl_notes, tbl_clients) while the 3rd is optional (tbl_notes_categories).
I've always used a LEFT JOIN in my queries with questionable correlating records to the primary table.
But I'm not getting any results with the query below.
Would someone point out how I'm using the LEFT JOIN incorrectly?
SELECT n.*, c.clientname, nc.notecategoryname
FROM tbl_notes n, tbl_clients c
LEFT JOIN tbl_notes_categories nc ON n.categoryid = nc.categoryid
WHERE n.clientid = c.clientid
AND c.clientid = 12345
ORDER BY n.dateinserted DESC
In fact, I'm getting a sql error.
#1054 - Unknown column 'n.categoryid' in 'on clause'
categoryid certainly does exist in tbl_notes
I probably need to brush up on how JOINS really work. I'm guessing I cannot have a LEFT JOIN with 2 database tables before it?
On a side note, I can foresee times when there will be multiple required tables, with several optional tables. (in this case tbl_notes_categories is optional)
Assuming the column categoryid exists in the tbl_notes table...
Try rewriting the query to use the JOIN syntax, rather than using the old-school comma as the join operator. (If the problem isn't a misnamed column, I suspect the problem is in mixing the two types of syntax... but this is just a suspicion, I have no reason to test mixing old-style comma joins with JOIN keywords.)
I'd write the statement like this:
SELECT n.*, c.clientname, nc.notecategoryname
FROM tbl_notes n
JOIN tbl_clients c
ON n.clientid = c.clientid
LEFT
JOIN tbl_notes_categories nc
ON nc.categoryid = n.categoryid
WHERE c.clientid = 12345
ORDER BY n.dateinserted DESC
(Actually, I would specify the individual columns to return from n, rather than using n.*, but that's just a style preference, not a SQL syntax requirement.)

Mixing ANSI 1992 JOINs and COMMAs in a query

i'm trying the following MySQL query to fetch some data:
SELECT m.*, t.*
FROM memebers as m, telephone as t
INNER JOIN memeberFunctions as mf ON m.id = mf.memeber
INNER JOIN mitgliedTelephone as mt ON m.id = mt.memeber
WHERE mf.function = 32
But i always get the following error:
#1054 - Unknown column 'm.id' in 'on clause'
The column does exists and the query works fine with only one table (e.g. when i remove telephone)
Does anybody know what I do wrong?
According to this link, you shouldn't mix up both notations when building up joins. The comma you are using to join memebers as m, telephone as t, and the subsequent calls to inner join, are triggering the unknown column error.
To deal with it, use CROSS/INNER/LEFT JOIN instead of commas.
Previously, the comma operator (,) and JOIN both had the same
precedence, so the join expression t1, t2 JOIN t3 was interpreted as
((t1, t2) JOIN t3). Now JOIN has higher precedence, so the expression
is interpreted as (t1, (t2 JOIN t3)). This change affects statements
that use an ON clause, because that clause can refer only to columns
in the operands of the join, and the change in precedence changes
interpretation of what those operands are.
For pedagogic purpose, I'm adding the query as it, I think, should be:
SELECT m.*, t.*
FROM memebers as m
JOIN telephone as t
JOIN memeberFunctions as mf ON m.id = mf.memeber AND mf.function = 32
JOIN mitgliedTelephone as mt ON m.id = mt.memeber
Since you're not joining t and m, the final result will be a cartesian product; you might want it to be revised.
I Hope it helped.
It seems your requirement is to join members table but you are joining with telephone table. just change their order.
SELECT
`m`.*,
`t`.*
FROM
`memebers` AS `m`
JOIN `telephone` AS `t`
JOIN `memeberFunctions` AS `mf`
ON `m`.`id` = `mf`.`memeber`
AND `mf`.`function` = 32
JOIN `mitgliedTelephone` AS `mt`
ON `m`.`id` = `mt`.`memeber`;
Hope this helps you. Thank you!!