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.
Related
Firstly, I'm a beginner to MySQL and I'm still learning. I'm trying to join 2 tables to display a count. Primarily, I use 2 codes. One code to display names -
SELECT tag_logs.timestamp, People.Name FROM `tag_logs` INNER JOIN People WHERE tag_logs.tag_no = People.nametag
Another code to display count of names -
SELECT tag_logs.tag_no, COUNT(tag_logs.tag_no) FROM tag_logs GROUP BY tag_no HAVING COUNT(tag_no) >= 1
I want to display Name and a count number, instead of a tag number and count. I attempted to join both tables by using the following code, however, I've had little luck -
SELECT People.Name FROM `tag_logs` INNER JOIN People WHERE tag_logs.tag_no = People.nametag AND COUNT(tag_logs.tag_no) FROM tag_logs GROUP BY tag_no HAVING COUNT(tag_no) >= 1
I'm given an error when I try to call 'FROM tag_logs' a second time. Is there a way to work around this?
I aim to make this my final result, except I should be able to see names instead of numbers.
Two tables are joined using ON clause. You should learn joins.
SELECT People.Name ,COUNT(tag_logs.tag_no)
FROM `tag_logs`
INNER JOIN People ON tag_logs.tag_no = People.nametag
GROUP BY tag_logs.tag_no
HAVING COUNT(tag_no) >= 1
It should be
SELECT People.Name FROM `tag_logs`
INNER JOIN People on tag_logs.tag_no = People.nametag
GROUP BY tag_no HAVING COUNT(tag_no) >= 1
EDIT
SELECT People.Name, COUNT(tag_no) FROM `tag_logs`
INNER JOIN People on tag_logs.tag_no = People.nametag
GROUP BY tag_no HAVING COUNT(tag_no) >= 1
I believe the query that you want looks like this:
SELECT p.Name, COUNT(*)
FROM tag_logs tl INNER JOIN
People p
ON tl.tag_no = p.nametag
GROUP BY p.Name;
Notes:
COUNT(*) is shorter than COUNT(tl.tag_no) and they do the same thing.
GROUP BY clause now matches the SELECT. If you could have people with the same names, then add p.nametag to the GROUP BY. A version use only GROUP BY tl.tag_no is invalid SQL and should fail in most databases, because of the non-matching p.Name in the SELECT.
The HAVING clause (HAVING COUNT(tag_no) >= 1) is unnecessary, because the INNER JOIN requires at least one match and tag_no is never NULL (because it is used for the JOIN).
I introduced table aliases, so the query is easier to write and to read.
What i would like to archieve:
Getting the correct sum of the total amount of the orders that has been cancelled of user id 2002.
Some pre information:
I am having deals which that has its price in deals.price and its id in deals.ID
I then have orders with a foreign key to deals.ID
Running this SQL:
select SUM(deals.price), orders.* from orders
JOIN deals ON deals.ID = orders.deal_id
where orders.user_id = 2002
and orders.cancelled = 1
Works just fine.
Here is where i get stuck:
As an addition to deals, each deals has products with their own prices.
Table is called deal_products, deal_products.price hold the price and deal_products.product_id has the ID of it.
A order is attached to a deal product in another table called order_products, where order_products.product_id = deal_products.product_id
To sum up: I would like to do is including a if inside the above SQL.
If a order has a row in order_products, get the order_products.product_id and find the price in deal_products (price) and use this instead of deals.price when SUM()'ing.
If there is no row it should use deals.price.
How can this be archieved? To first look in another table if there is a entry, and then further look in to a third table and get a value to use?
You can use COALESCE + LEFT JOIN:
select SUM(coalesce(dp.price, d.price)), o.*
from orders o JOIN deals d ON d.ID = o.deal_id
LEFT JOIN order_products op on op.order_id = o.id
LEFT JOIN deal_products dp on op.product_id = dp.product_id
where o.user_id = 2002 and o.cancelled = 1
group by ...;
COALESCE function returns first not null operand
LEFT [OUTER] JOIN = [INNER] JOIN + all rows of the structure on the left side of the LEFT JOIN keyword, which don't match the ON clause in the right structure.
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.
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.
Here is the schema of the database I'm working with - [redacted]
I'm trying to come up with 2 different queries for 2 different result sets -
Sales representatives with the highest sales
Sales representatives with the highest sales grouped by managerId
I've had some luck with the 1st query; this is what I came up with:
SELECT
SUM(`products`.`cost`) AS `Sale`
, `employees`.`firstName`
FROM
`d2dpro`.`sales_reps`
, `d2dpro`.`products`
INNER JOIN `d2dpro`.`employees`
ON (`sales_reps`.`employeeId` = `employees`.`employeeId`)
INNER JOIN `d2dpro`.`sold_products`
ON (`products`.`productId` = `sold_products`.`productId`)
INNER JOIN `d2dpro`.`sales`
ON (`sold_products`.`saleId` = `sales`.`saleId`) AND (`sales`.`salesCampId` = `sales_reps`.`saleCampId`)
GROUP BY `employees`.`firstName`;
With this query, I'm stuck with this error:
Error Code: 1054
Unknown column 'sales_reps.saleCampId' in 'on clause'
Any help with this query? And also for the 2nd one?
You are using one table (sales_reps) that is CROSS JOIN-ed with the INNER JOIN of the tables employees, sold_products and sales. To be able to reference sales_reps in that JOIN you should include it as inner join: (the FROM clause should look like this)
FROM `d2dpro`.`products`
INNER JOIN `d2dpro`.`employees`
ON (`sales_reps`.`employeeId` = `employees`.`employeeId`)
INNER JOIN `d2dpro`.`sold_products`
ON (`products`.`productId` = `sold_products`.`productId`)
INNER JOIN `d2dpro`.`sales`
ON (`sold_products`.`saleId` = `sales`.`saleId`)
INNER JOIN `d2dpro`.`sales_reps`
ON (`sales`.`salesCampId` = `sales_reps`.`saleCampId`)