SQL Error, Column Doesn't Exist - sql

The following error:
Unknown column 'Customers.Customer_ID' in 'on clause'
Is a result of this code:
SELECT First_Name, Last_Name, Orders.Order_ID, Orders.Order_Date, Orders.Plant_ID, Orders.Plant_Qty, Orders.Price, Orders.Employee_ID
FROM Customers, Orders
INNER JOIN Orders as t2
ON Customers.Customer_ID = t2.Order_ID;
I cannot work out why; Customers.Customer_ID is a field in the Customers table?

Probably because it's ambiguous. You need to remove FROM .. Orders since it looks like you're trying to do an explicit join. I would also recommend prefixing all column names in your column list. You should also stick to an alias or the table name on your join.
SELECT customers.first_name,
customers.last_name,
orders.order_id,
orders.order_date,
orders.plant_id,
orders.plant_qty,
orders.price,
orders.employee_id
FROM customers
INNER JOIN orders
ON customers.customer_id = orders.order_id;

I believe that Customers -> Orders (one to many relationship) and you're trying to join the table one to one relationship, correct me if i am wrong. so the query should like this.
SELECT First_Name, Last_Name, Orders.Order_ID, Orders.Order_Date, Orders.Plant_ID, Orders.Plant_Qty, Orders.Price, Orders.Employee_ID
FROM Customers
INNER JOIN Orders as t2
ON Customers.Customer_ID = t2.Customer_ID;

Related

Multiple inner join, correct syntax

I think I have either misunderstood the syntax or there is another syntax for multiple joins.
So, I ran across following query (SQLite3):
cur.execute('''Select department_name AS 'Department',
(Employees.first_name ||' '|| Employees.last_name) AS 'Salesman',
Orders.order_id AS 'OrderID',
Products.product_name AS 'Product',
ProductsOrders.cost AS 'Sales_Worth'
From Departments
Inner JOIN Employees ON Employees.department_id = Departments.department_id
Inner JOIN Orders ON Orders.employee_id = Employees.employee_id
INNER JOIN Products ON Products.product_id = ProductsOrders.product_id
INNER JOIN ProductsOrders ON ProductsOrders.order_id = Orders.order_id
ORDER BY Department''')
Clearly : department_name is a field of Departments table.
But, how can we state all of the above using only "From Departments"
If Orders.order_id, Products.product_name, ProductsOrders.cost are not fields of Departments table?
Shouldn't we be stating:
FROM Orders, FROM Products, FROM ProductsOrders
as well?
(I have obeyed the following syntax before):
SELECT columns
FROM table1
INNER JOIN table2
ON table1.column_name = table2.column_name;
Shouldn't we be stating FROM Orders, FROM Products, FROM
ProductsOrders as well?
Something like this already exists and it is valid and allowed in most databases:
SELECT Departments.department_name AS 'Department',
(Employees.first_name ||' '|| Employees.last_name) AS 'Salesman',
Orders.order_id AS 'OrderID',
Products.product_name AS 'Product',
ProductsOrders.cost AS 'Sales_Worth'
FROM Departments, Employees, Orders, Products, ProductsOrders
WHERE Employees.department_id = Departments.department_id
AND Orders.employee_id = Employees.employee_id
AND Products.product_id = ProductsOrders.product_id
AND ProductsOrders.order_id = Orders.order_id
ORDER BY Department
But the above syntax has been replaced by the ANSI-compliant syntax that uses the keywords INNER JOIN and one ON clause for each joined table (instead of stacking all the join conditions in the WHERE clause).
Although the 2 syntaxes are equivalent in terms of performance (at least for SQLite), the new syntax is what you should learn, because in time you will find that it is more readable, flexible and descriptive of what you are doing (especially when you deal with other types of joins such as CROSS/LEFT/RIGHT/FULL joins).
As a sidenote: never use single quotes for table/column names/aliases. Use (if needed) double quotes, backticks or square brackets.
If you do a join, you are selecting from the result of the join, not the original table, so you only need to specify the table (or its alias) if the column's name is ambiguous.
Select department_name AS 'Department'
The key with this is to make sure you alias the table. If more than one table has a given field name, your query will fail
Shouldn't we be stating FROM Orders, FROM Products, FROM ProductsOrders as well?
Not really. The point of JOIN is to pull from multiple tables that are related. If there are unrelated records, consider a separate query.

SQL dividing a count from one table by a number from a different table

I am struggling with taking a Count() from one table and dividing it by a correlating number from a different table in Microsoft SQL Server.
Here is a fictional example of what I'm trying to do
Lets say I have a table of orders. One column in there is states.
I have a second table that has a column for states, and second column for each states population.
I'd like to find the order per population for each sate, but I have struggled to get my query right.
Here is what I have so far:
SELECT Orders.State, Count(*)/
(SELECT StatePopulations.Population FROM Orders INNER JOIN StatePopulations
on Orders.State = StatePopulations.State
WHERE Orders.state = StatePopulations.State )
FROM Orders INNER JOIN StatePopulations
ON Orders.state = StatePopulations.State
GROUP BY Orders.state
So far I'm contending with an error that says my sub query is returning multiple results for each state, but I'm newer to SQL and don't know how to overcome it.
If you really want a correlated sub-query, then this should do it...
(You don't need to join both table in either the inner or outer query, the correlation in the inner query's where clause does the 'join'.)
SELECT
Orders.state,
COUNT(*) / (SELECT population FROM StatePopulation WHERE state = Orders.state)
FROM
Orders
GROUP BY
Orders.state
Personally, I'd just join them and use MAX()...
SELECT
Orders.state,
COUNT(*) / MAX(StatePopulation.population)
FROM
Orders
INNER JOIN
StatePopulation
StatePopulation.state = Orders.state
GROUP BY
Orders.state
Or aggregate your orders before you join...
SELECT
Orders.state,
Orders.order_count / StatePopulation.population
FROM
(
SELECT
Orders.state,
COUNT(*) AS order_count
FROM
Orders
GROUP BY
Orders.state
)
Orders
INNER JOIN
StatePopulation
StatePopulation.state = Orders.state
(Please forgive typos and smelling pistakes, I'm doing this on a phone.)

How to avoid the "ambiguous" error message when using joins to create several tables

I'm trying to use the following code to create a list of customers and their brands that they buy. The brands table has the brand name and customer_id is in the customers table. To link them I have to get the brand_id and receipt_id linked together via the receipts table (connects to customers table) and receipt_item_details1 table (connects to brands table).
So, receipt_item_details1 table (has brand_id column to then connect to brands table) and new table customer_receipts (created by first inner most subquery) are trying it to be linked by receipt_id. I'd like to show the customer_id column when I build my table joining these two table (an original: receipt_item_details1 joined to a new table: customer_receipts).
ISSUE: I keep getting the following error. how do Infix it and also list the brands?
"column reference "customer_id" is ambiguous
LINE 3: ...pts.receipt_id, receipt_item_details1.receipt_id, customer_r.."
SELECT customer_brandids.brand_id, brands.brand_id, customer_brandids.customer_id, brands.brand_name
FROM
(SELECT customer_receipts.receipt_id, receipt_item_details1.receipt_id, customer_receipts.customer_id, receipt_item_details1.brand_id
FROM
(SELECT receipts.customer_id, customers.customer_id, receipts.receipt_id
FROM receipts
INNER JOIN customers
ON receipts.customer_id = customers.customer_id) AS customer_receipts
INNER JOIN receipt_item_details1
ON customer_receipts.receipt_id = receipt_item_details1.receipt_id) AS customer_brandids
INNER JOIN brands
ON customer_brandids.brand_id = brands.brand_id
Your inner subselect
(SELECT receipts.customer_id, customers.customer_id
generates a result with two columns named customer_id. So your next higher subselect cannot differ between both columns if you reference customer_id
You should give one or both an alias:
(SELECT receipts.customer_id as r_customer_id,
customers.customer_id as c_customer_id
Then your next higher query can call
SELECT customer_receipts.c_customer_id...
So first step of solving the problem:
SELECT
customer_brandids.brand_id,
brands.brand_id,
customer_brandids.c_customer_id, --> reference alias
brands.brand_name
FROM
(SELECT
customer_receipts.receipt_id as c_receipt_id, --> same problem
receipt_item_details1.receipt_id as r_receipt_id,
customer_receipts.c_customer_id, --> reference alias
receipt_item_details1.brand_id
FROM
(SELECT
receipts.customer_id as r_customer_id, --> here was the problem
customers.customer_id as c_customer_id,
receipts.receipt_id
FROM receipts
INNER JOIN customers
ON receipts.customer_id = customers.customer_id) AS customer_receipts
INNER JOIN receipt_item_details1
ON customer_receipts.receipt_id = receipt_item_details1.receipt_id) AS customer_brandids
INNER JOIN brands
ON customer_brandids.brand_id = brands.brand_id
Addionally:
You don't need to take both columns (e.g. of receipt_id) because of the INNER JOIN it is ensured that both columns have the same value
You can use aliases to shorten your query.
You don't need to create a subquery for each join. Just join.
All in all, this should do the same:
SELECT b.brand_id, c.customer_id, b.brand_name
FROM receipts r
INNER JOIN customers c ON r.customer_id = c.customer_id
INNER JOIN receipt_item_details1 rid ON r.receipt_id = rid.receipt_id
INNER JOIN brands b ON b.brand_id = rid.receipt_id
demo: db<>fiddle
Do not use nested selects when it is not necessary, try to use joins, and query will be more simple and will look something like this
select * from receipts
join customers on receipts.customer_id = customers.customer_id
join receipt_item_details1 on receipts.receipt_id = receipt_item_details1.receipt_id
join brands on receipt_item_details1.brand_id = brands.brand_id
Instead of asterisk you can define columns you want to get

What am I doing wrong? Joins again?

Okay, I've perused this site, a couple that members here have suggested, sql textbooks, etc.
The problem:
List customer name, order date, number ordered, quoted price, amount billed and description for items ordered from Premiere Products. Organize this report by order date with customer name
The tables:
SQL> desc customer
Name
----------------------
CUSTOMER_NUM
CUSTOMER_NAME
STREET
CITY
STATE
ZIP
BALANCE
CREDIT_LIMIT
REP_NUM
SQL> desc orders
Name
----------------------
ORDER_NUM
ORDER_DATE
CUSTOMER_NUM
SQL> desc order_line
Name
----------------------
ORDER_NUM
PART_NUM
NUM_ORDERED
QUOTED_PRICE
SQL> desc part
Name
----------------------
PART_NUM
DESCRIPT
ON_HAND
CLASS
WAREHOUSE
PRICE
Here's what I am using for a query:
SQL> SELECT CUSTOMER.CUSTOMER_NAME, ORDERS.ORDER_DATE,
2 ORDER_LINE.NUM_ORDERED, ORDER_LINE.QUOTED_PRICE,
3 SUM(Num_Ordered*Quoted_Price) AS Amt_Billed,
4 PART.DESCRIPT
5 FROM customer
6 INNER JOIN CUSTOMER INNER JOIN ORDERS ON
CUSTOMER.CUSTOMER_NUM =ORDERS.CUSTOMER_NUM
7 INNER JOIN ORDER_LINE ON ORDERS.ORDER_NUM = ORDER_LINE.ORDER_NUM
8 Inner JOIN ORDER_LINE ON PART.PART_NUM = ORDER_LINE.PART_NUM;
Inner JOIN ORDER_LINE ON PART.PART_NUM = ORDER_LINE.PART_NUM
*
ERROR at line 8:
ORA-00905: missing keyword
Ive tried it several times, even made an access table for it, and the SQL there is basically the same as what I have here. I'm using Oracle 11g.
Getting your SQL formatted helps follow the relationships between the tables. Notice my simplified indentation and showing the left-side table joined to the right-side and the ON clause shows columnar relation between them.
Once that is done, then get the rest of your columns for selection, summation, group by, order by, etc
SELECT
c.customer_name,
o.order_date,
ol.num_ordered,
ol.quoted_price,
ol.num_ordered * ol.quoted_price as amt_Billed,
p.descript
from
customer c
join orders o
ON c.customer_num = o.customer_num
join order_line ol
ON o.order_num = ol.order_num
join part p
ON ol.part_num = p.part_num
order by
o.order_date,
c.customer_name
Since your query is showing the amount per line item of things ordered, you dont need a "SUM()", you can just multiply the columns outright as a per-line total amount as you are showing each part actually ordered.
Also notice the simplified alias name references of each table vs writing full length of each table name repeatedly.
Yeap, joins again :)
INNER JOIN CUSTOMER INNER JOIN ORDERS ON
You're missing the ON in CUSTOMER or you have an extra INNER JOIN CUSTOMER. Most likely the second one.
try
SQL> SELECT CUSTOMER.CUSTOMER_NAME, ORDERS.ORDER_DATE,
ORDER_LINE.NUM_ORDERED, ORDER_LINE.QUOTED_PRICE,
SUM(Num_Ordered*Quoted_Price) AS Amt_Billed,
PART.DESCRIPT
FROM customer
INNER JOIN ORDERS ON CUSTOMER.CUSTOMER_NUM =ORDERS.CUSTOMER_NUM
INNER JOIN ORDER_LINE ON ORDERS.ORDER_NUM = ORDER_LINE.ORDER_NUM
Inner JOIN PART ON PART.PART_NUM = ORDER_LINE.PART_NUM;
Line 6 was an incorrect JOIN statement
Line 8 was joining to wrong table

SQL statement to get all customers with no orders

I have a typical Persons table and an Orders table defined in such a way that I can do JOIN query as the following to return Orders for all Persons.
SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
FROM Persons
INNER JOIN Orders
ON Persons.id=Orders.Person_id
The question is, how do I write a statement that would return all Persons with NO Orders?
I'm using mysql.
Thank all in advance.
You may want to use LEFT JOIN and IS NULL:
SELECT Persons.LastName, Persons.FirstName
FROM Persons
LEFT JOIN Orders ON Persons.id = Orders.Person_id
WHERE Orders.Person_id IS NULL;
The result of a left join always contains all records of the "left" table (Persons), even if the join-condition does not find any matching record in the "right" table (Orders). When there is no match, the columns of the "right" table will NULL in the result set.
This should work... theres more than one way to do it.
select * from persons where person.id not in (select person_id from orders)
Just for completeness, here is the not exists version:
select * from persons p
where not exists
(select null from orders o where o.person_id = p.id)
You can use left join:
SELECT DISTINCT o.CustomerID from Orders as o
left join Customers as c
on o.CustomerID=c.CustomerID
Question
Find customers who have never made an order.
Output the first name of the customer.
Data
Two tables: Customers and Orders
SELECT first_name
from customers
WHERE first_name not in
(select first_name
from customers
join orders on customers.id=orders.cust_id)