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.
Related
I have to obtain the male employee with highest number of requests in the second half of April 2014.
I have these tables:
Employee (EmployeeID, firstName, LastName, gender)
Workplace (CompanyID, EmployeeID, CompanyName)
Extras (ExtraID, CompanyID, Requests, Description, Date)
Extras.Requests is a string, not numerical.
My SQL attempt looks like this:
SELECT
Employee.FirstName, Employee.LastName,
SUM(COUNT(Extras.ExtraID)
FROM
Employee
INNER JOIN
(Workplace
INNER JOIN
Extras ON Workplace.CompanyID = Extras.CompanyID)
ON Workplace.EmployeeID = Employee.EmployeeID
WHERE
Employee.Gender = "male"
AND Extras.Date BETWEEN #4/15/2014# AND #4/30/2014#
SORT BY
SUM(COUNT(Extras.ExtraID) DESC;
LIMIT 1;
I'm not sure if my query is correct or not, thanks in advance.
There are several issues with your querySUM(COUNT(...)) nesting aggregate functions like this isn't permitted
You also need a GROUP BY clause to use aggregation function with non-aggregating columns (which are Employee.FirstName, Employee.LastName in your query).
Sorting is performed by an ORDER BY clause
Your original query includes a nested inner join which is likely to produce unexpected results.
FROM Employee
INNER JOIN(Workplace
INNER JOIN Extras ON Workplace.CompanyID=Extras.CompanyID
) ON Workplace.EmployeeID=Employee.EmployeeID
While nesting joins is allowed it is rarely used, I suggest you avoid it.
I would expect the query to look more like this
SELECT
Employee.FirstName, Employee.LastName, COUNT(Extras.ExtraID)
FROM ((Employee
INNER JOIN Workplace
ON Workplace.EmployeeID = Employee.EmployeeID)
INNER JOIN Extras
ON Workplace.CompanyID = Extras.CompanyID)
WHERE Employee.Gender = "male"
AND Extras.Date BETWEEN #4/15/2014# AND #4/30/2014#
GROUP BY
Employee.FirstName
,Employee.LastName
ORDER BY
COUNT(Extras.ExtraID) DESC;
LIMIT 1;
It's been years since I used access, I think it still wants parentheses in the from clause as I've shown above. In most SQL implementation they are not required, and it is more common for literals to use single quotes e.g. WHERE Employee.Gender = 'male'.
Say I have two tables, employee (with a character column id along with some other columns) and orders, with a column employeeid and partno, along with some other ids.
Is it more efficient to say
select *
from employees, orders
where id = employeeid
and id = '22222'
or
select *
from employees, orders
where id = '22222'
and employeeid = '22222'
or does it not really matter?
It looks like you're trying to do a join and in that case the second form isn't going to work as expected, it's going to produce an error. The first would look like this once qualified:
select * from employees, orders where orders.id = employees.id and employees.id = '22222'
The first equality is really specifying the condition to use when selecting rows from the orders table to join with a particular row from the employees table. The second is the one that's a conventional where selection criteria.
The second check is unnecessary. Oracle is smart enough to know that if A=B and B=C then A=C. You don't need to tell it.
The best way to write that query is
SELECT *
FROM employees e
INNER JOIN orders o ON o.employeeid = e.id
WHERE e.id = '22222'
Even if the best possible plan is to start by reading all the rows from orders where employeeid is '22222', Oracle will know to do it even though you didn't explicitly specify the condition
AND o.employeeid = '22222'
Oracle infers the condition from the others that you did specify.
After executing the code below, i get an ORA-25155 error
SELECT p.prod_id, prod_name, prod_list_price,quantity_sold,cust_last_name
FROM products p NATURAL JOIN sales s NATURAL JOIN customer c
WHERE prod_id = 148;
As suggested on a comment, this ORA-25155 error suggests that you're qualifying the column name "p.prod_id" instead of just "prod_id". That is what is triggering your error.
Try this fully working SQL Fiddle code. Your query should be:
SELECT prod_id, prod_name, prod_list_price,quantity_sold,cust_last_name
FROM products
NATURAL JOIN sales
NATURAL JOIN customer
WHERE prod_id = 148;
A NATURAL JOIN over multiple tables will join one pair of tables, then join the third table to the result and so forth. NATURAL JOIN syntax has no explicit join predicate, so the qualifiers aren't used there.
natural join in Oracle joins two tables on the columns in each table that have common names. Hence after the join, you shouldn't refer to a column which is common between the tables that have been naturally join with an alias, as the alias is redundant.
This is similar to the way using() works in a join clause.
The right command is:
SELECT * FROM products p NATURAL JOIN sales s NATURAL JOIN customer c
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;
When i written the query like the following.. It's written the combination of all the records.
What's the mistake in the query?
SELECT ven.vendor_code, add.address1
FROM vendor ven INNER JOIN employee emp
ON ven.emp_fk = emp.id
INNER JOIN address add
ON add.emp_name = emp.emp_name;
Using inner join, you've to put all the links (relations) between two tables in the ON clause.
Assuming the relations are good, you may test the following queries to see if they really make the combination of all records:
SELECT count(*)
from vendor ven
inner join employee emp on ven.emp_fk = emp.id
inner join address add on add.emp_name = emp.emp_name;
SELECT count(*)
add.address1
from vendor ven, employee emp, address add
If both queries return the same result (which I doubt), you really have what you say.
If not, as I assume, maybe you are missing a relation or a restriction to filter the number of results.