This question already has answers here:
Difference between these two joining table approaches?
(4 answers)
Closed 8 years ago.
I have two set of sql queries. Both produces the desired result for me but I am not sure which one is efficient and how. Please anybody can explain it to me?
Query 1:
SELECT
od.id, od.order_id, c.firstname, od.category, od.quantity,
od.price, o.order_date, u.username
FROM
orders o inner join order_detail od on o.id=od.order_id
join customer c on c.customerid = o.customer_id
join users u on u.userid = o.issued_by;
Query 2:
SELECT
od.id, od.order_id, c.firstname, od.category, od.quantity,
od.price, o.order_date, u.username
FROM
order_detail od, customer c, orders o,
users u WHERE o.id = od.order_id
AND o.customer_id = c.customerid
AND u.userid = o.issued_by;
The first query is the better one with the appropriate syntax. The second query is an "old school" version and should not be used.
In term of performance there is an important difference between both queries, the first one will filter the result directly during the jointure clauses. The second query will get the entire data before applying the WHERE clause on them.
Don't hesitate, choose the first version without any doubt.
Hope that this will help you.
Related
This question already has answers here:
conditional join in mysql
(4 answers)
Closed 6 years ago.
I have a little complicated query here. I have to select columns by names cant just user 'orders.*. because i have multiple columns from different tables with the same name.
What I'm trying to do is to select specific fields from orders,users,payment_methods_translation and join bank_accounts_translation only if the orders.payment_method_id = '3'
SELECT
orders.id as orderid,
orders.final_total,
orders.user_id,
orders.auto_cancel,
users.id as userid,
users.first_name,
payment_methods_translation.payment_method_id,
payment_methods_translation.name
FROM
orders,users,
payment_methods_translation
WHERE
orders.id='$id' AND
orders.user_id = users.id AND
orders.payment_method_id = payment_methods_translation.payment_method_id AND
orders.auto_cancel='1'
JOIN
bank_accounts_translation ON (orders.payment_method_id='3'
AND orders.bank_id = bank_accounts_translation.bank_account_id)
But I get a mysql error. So how can I select all the fields from bank_accounts_translation only if orders.payment_method_id = '3' and orders.bank_id = bank_accounts_translation.bank_id
Left join should do it... I
Refactored the code to use the current ANSI standards, you appear to be mixing them.
used table aliases to improve readability.
LEFT JOIN says return all records from prior listed tables and only those that match the on criteria of the table being joined to.
SELECT O.id as orderid
,O.final_total
,O.user_id
,O.auto_cancel
,u.id as userid
,u.first_name
,PMT.payment_method_id
,PMT.name
FROM orders O
INNER JOIN users U
ON O.user_id = U.id
INNER JOIN payment_methods_translation PMT
ON O.payment_method_id = PMT.payment_method_id
LEFT JOIN bank_accounts_translation BAT
ON O.payment_method_id='3'
and O.bank_id = BAT.bank_account_id
WHERE O.id='$id'
and O.auto_cancel='1'
Can you tell me what I need to manipulate in this query to get it working?
select C.ID from
(select A.ID from CUSTOMERS A inner join PROFILES B on A.ID=B.ID where CTR='67564' and CST_CD in
('G','H')) as C
inner join
(select ID from RELATION_CODES where R_CD='KC') as R
on C.ID=R.ID
The individual inner queries are working just fine and giving correct results, not sure what is the problem with inner join in from clause..
Not completely sure I'm understanding your question, but this should be able to be rewritten without the subqueries:
select c.id
from customers c
join profiles p on c.id = p.id
join relation_codes rc on rc.id = c.id
where ctr = '67564'
and cst_cd in ('G','H')
and rc.r_cd = 'KC'
If this isn't working, please provide your table structure and sample data and expected results. This should get you pretty close though.
I have to ask, is the id field in the relation_codes table and the profiles table the same as the id in the customers table. Perhaps you need to identify how your tables are related.
A Visual Explanation of SQL Joins
This question already has answers here:
INNER JOIN ON vs WHERE clause
(12 answers)
Closed 7 years ago.
I have two queries:
$query = mysql_query("SELECT ord.orderID, customers.CustomerName,
FROM ord, customers
WHERE customers.CustomerSalary=ord.orderID");
and
$query = mysql_query("SELECT ord.orderID, customers.CustomerName,
FROM ord
INNER JOIN customers
ON customers.CustomerSalary=ord.orderID");
This queries return the same result. What is different between them.
$query = mysql_query("SELECT ord.orderID, customers.CustomerName,
FROM ord
INNER JOIN customers
ON customers.CustomerSalary=ord.orderID");
This query is optimised than the other one as Inner join get applied first and then where clause will be applied.
Other benifit I see that is you can change Inner Outer join.
Clean code.
Both are same. The first query is basically inner join on the back-end but the way you have written second query, you can use left join, right join etc with that query.
Both will perform Cartesian Product on the back-end and filter out the results based on the check.
You will need to use the second query format in order to use left join, right join etc.
Another approach commonly used is known as nested queries. They are pretty faster than joins since there is no Cartesian product on the back-end.
Ok, so Ive been trying to get this query working for hours now, but nothing I seem to do will get me the results I am after.
SELECT COALESCE(SUM(ps.cost), 0) AS ps_total
FROM Customers c
LEFT JOIN ProductSales ps ON c.customer_ID = ps.customer_ID
GROUP BY c.sex;
SELECT COALESCE(SUM(hc.cost), 0) AS hc_total
FROM Customers c
LEFT JOIN HairCuts hc ON c.customer_ID = hc.customer_ID
GROUP BY c.sex;
So the above two queries work fine. Each one finds the total spent on either products or hair cuts and groups by gener thus giving me the total spent on cuts and products for males and females individually.However somehow I need to combine these in such a way that I can display the gender(s) that spent more on products than on haircuts.
Any help with this would be very much appreciated.
P.S hopefully the question is clear enough. If not Ill try to elaborate.
Another way you can join your both query results as
SELECT t1.sex,
COALESCE(t1.ps_total - t2.hc_total,0) AS `difference`
FROM
(SELECT COALESCE(SUM(ps.cost), 0) AS ps_total ,c.sex
FROM Customers c
LEFT JOIN ProductSales ps ON c.customer_ID = ps.customer_ID
GROUP BY c.sex) t1
LEFT JOIN
(SELECT COALESCE(SUM(hc.cost), 0) AS hc_total ,c.sex
FROM Customers c
LEFT JOIN HairCuts hc ON c.customer_ID = hc.customer_ID
GROUP BY c.sex) t2
USING(sex)
HAVING difference > 0
Edit from comments
I have used a short syntax for ON() clause like USING(sex) = ON(t1.sex=t2.sex) if you have a same name for a column in both tables you can use USING() if you have different then you need to use ON() syntax
Like
Table1 column(category_id primary key,...)
Table2 column(category_id foreign key,...)
Then you can easily use USING()
SELECT * FROM
Table1
JOIN Table2
USING(category_id )
But if you have different name for association then you need to use ON() clause
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.