How to get the right output from this query - sql

Im creating a sql query that outputs the licensePlate from dbo.car when there is any stock of the car. Which means i will have to look under dbo.Sell and dbo.Rent to make sure that a car is not sold or under rental.
I need to have a output with the following:
LicensePlateNo
--------------
SGK5556A
But the output will always be blank.
I have the following statement:
SELECT
LicensePlateNo
FROM car
INNER JOIN CarTransaction ON
car.ChassisNo = CarTransaction.ChassisNo
INNER JOIN Sell on
CarTransaction.TransactionID = Sell.TransactionID
INNER JOIN Rent on
CarTransaction.TransactionID = Rent.TransactionID
WHERE
Car.Make = 'Toyota' AND
Sell.TransactionID IN (SELECT TransactionID FROM Sell) AND
Rent.TransactionID IN (SELECT TransactionID FROM Rent)
I cant seem to get the right query. The only moment when the query works is when i did not specify the query for dbo.Rent. But i need to validate whether if the car is available through the rental history

The inner joins are not needed and the car is never in sell and rent at the same time, query can be written as:
SELECT
LicensePlateNo
FROM
Car
INNER JOIN
CarTransaction
ON
Car.ChassisNo = CarTransaction.ChassisNo
WHERE
Car.Make = 'Toyota' AND
CarTransaction.TransactionID NOT IN (SELECT TransactionID FROM Sell) AND
CarTransaction.TransactionID NOT IN (SELECT TransactionID FROM Rent)
;

This query will only produce results if you have a car that has been sold and has been under rental. That is what INNER JOINs are for - they only give results when a record is found in both tables.
I guess you want a SQL statement like this:
SELECT LicensePlateNo FROM car
LEFT JOIN CarTransaction ON car.ChassisNo = CarTransaction.ChassisNo
LEFT JOIN Sell ON CarTransaction.TransactionID = Sell.TransactionID
LEFT JOIN Rent ON CarTransaction.TransactionID = Rent.TransactionID
WHERE Car.Make = 'Toyota'
AND Sell.TransactionID IS NULL
AND Rent.TransactionID IS NULL

Related

LEFT JOIN with condition in WHERE clause

SELECT
supplies.id,
supplierId,
supplies.date,
supplies.commodity,
supplier_payments.date AS paymentDate,
FROM
supplies
INNER JOIN suppliers ON suppliers.id = supplies.supplierId
LEFT JOIN supplier_payments ON supplier_payments.supplyId = supplies.id
WHERE supplier_payments.isDeleted = 0 AND supplierId = 1
What I am trying is to get all records from supplies table and related records from supplier_payments but the supplier_payments.isDeleted should be equal to 0. What happens now that I only get records from supplies that have at least one supplier payment because of the condition. Is there a way to get all supply records and supply payments with condition?
Consider moving the condition on the LEFT JOINed table to the ON clause of the JOIN:
SELECT
sr.id,
se.supplierId,
se.date,
se.commodity,
sp.date AS paymentDate,
FROM supplies se
INNER JOIN suppliers sr ON sr.id = se.supplierId
LEFT JOIN supplier_payments sp
ON sp.supplyId = se.id
AND sp.isDeleted = 0
WHERE se.supplierId = 1
Side notes:
in a multi-table query, always qualify each column with the table it belongs to, to make the query easier to follow and avoid ambiguity
table aliases make the query easier to read and write

Is it necessary to filter the outer query in a join?

Query:
SELECT i1.*
FROM (SELECT store_id,
transaction_fid
FROM transactions i
inner join (SELECT prod_id
FROM products
WHERE category = '802') p
ON i.prod_id = p.prod_id
WHERE i.date_id = '10-SEP-16') i1
inner join transactions i2
ON i1.store_id = i2.store_id
AND i1.transaction_fid = i2.transaction_fid
In the above query, I'm trying to get transactions that have items that belong to the category '802'
The inner query matches each line from transactions where prod_id is a prod_id of an item in category 802.
The outer query then takes the store_id and transaction_fid and joins them back to the transaction table to get all other items in the matched transactions.
My question is - do i need to filter the outer query to be in the same date range as the inner query, or does it not matter in terms of efficiency/how long the query takes to run?
Is there a better way to achieve what I'm trying to do?
based on your table names and join types the query should something like :
select i1.store_id,i1.transaction_fid
from transactions i1
inner join products p
on i1.prod_id = p.prod_id
where p.category = '802'
and i1.date_id = '10-SEP-16'
Simple as this?
SELECT tr.*
FROM transactions AS tr
INNER JOIN products AS p ON p.prod_id=tr.prod_id
WHERE i.date_id = {d'2016-09-10'}
AND pr.category='802' --really string value? If int-value better as naked number
Btw: You really should avoid date/time value as culture depending string literals!

Basic SQL Joining Tables

Having a bit of trouble with a basic SQL problem.
The question is that I have to find the salespersons first and last name, then their Social Insurance Number, the product description, the product price, and quantity sold where the total quantity sold is greater than 5.
I'll attach the database information below as a photo.
Product quantity sold greater than 5
SELECT ProductId
FROM ProductsSales
HAVING SUM(QuantitySold) > 5
Use that to get the rest:
SELECT s.FirstName, s.LastName, s.SIN, p.ProductDescription, ps.UnitSalesPrice, ps.QuantitySold
FROM ProductsSales ps
LEFT JOIN Products p on p.ProductID = ps.ProductID
LEFT JOIN Salesmen s on s.SalesmaneID = ps.SellerID
WHERE ps.ProductID IN
(
SELECT ProductId
FROM ProductsSales
GROUP BY ProductId
HAVING SUM(QuantitySold) > 5
)
SELECT a.FirstName, a.LastName, a.SIN, c.ProductDescription, b.UnitSalesPrice, b.QuantitySold
FROM Salesmen a
LEFT JOIN ProductsSales b
ON a.SalesmanId = b.SellerId
LEFT JOIN Products c
ON b.ProductId = c.ProductId
WHERE b.QuantitySold > 5
Select a.FirstName, a.LastName, a.SIN From Salesmen as a,
c.ProductDescriptio, c.Price, b.sum(QunatitySold)
inner join ProductSales as b on a.Salesmanid = b.sellerid
inner join Products as c on c.ProductId = b.ProductId
having b.sum(QunatitySold)> 5
group by a.FirstName, b.ProductDescription
Brad,
Welcome to SQL. Joining for me was a terrifying experience when I first started but its really easy. The general concept is this:
Pick a Join
If you want to see all records that would be common between the two table, you would use and JOIN. If you wanted to combine the two tables but still show all records you use LEFT JOIN
The basic syntax is
SELECT fieldnames FROM tablename alias
JOIN othertable alias ON firstalias.field = secondalias.field
--Example
SELECT animal, food, idtag from animals a
JOIN food f on a.animalid = f.animalid
This assumes you have a common field animalid in both the animals table and the food table. you should also ideally preface the field names with the alias to make it easier to understand like this: a.animal, f.food
And you keep going until you have joined all the tables you need.
Make sure you only request field names you want
Hope that helps

SQL: Selecting multiple columns from multiple tables

I am using MS Access 2013.
I am trying to selecting the number and name from Salesperson table. Number, name and postcode from Customers table as well as all the information from the CarSale table all within the past month and order by salesperson no.
I have come up with the following
SELECT CS.carNo, CS.dateOfSale, SA.salespersonNo, SA.name AS SalesName,
CU.customerNo, CU.name AS CustName, CU.postCode
FROM CarSale AS CS, Car AS C, Salesperson AS SA, Customer AS CU
WHERE CS.carNo = C.carNo AND CS.salespersonNo = SA.salespersonNo
AND CS.customerNo = CU.customerNo AND dateOfSale BETWEEN #01/09/2016#
AND #02/09/2016#
ORDER BY CS.salespersonNo;
However as you can see, this is butt-ugly! I did some research and found that I should be using "JOINS" so I went ahead and included them, this is where my problem starts.
After inserting the JOINS into the query I get something that looks like this:
SELECT CS.carNo, CS.dateOfSale, SA.salespersonNo, SA.name AS SalesName,
CU.customerNo, CU.name AS CustName, CU.postCode
FROM CarSale AS CS
JOIN Car AS C ON CS.carNo = C.carNo
JOIN Salesperson AS SA on CS.salespersonNo = SA.salespersonNo
JOIN Customer AS CU ON CS.customerNo = CU.customerNo
WHERE cs.dateOfSale BETWEEN #01/09/2016# AND #02/09/2016#
ORDER BY CS.salespersonNo;
Here are the tables:
**CarSale**
carNo salespersonNo customerNo dateOfSale
-------------------------------------------------------
**Salesperson**
salespersonNo name contactNo monthlySalary centreNo
--------------------------------------------------------------
**Customer**
customerNo name contactNo postCode
---------------------------------------------
The error I am getting is "Syntax error in FROM clause."
I think you're close, but there is something wonky about your JOINs - you have a join on 'Car', but that's not one of your tables. JOINing occurs between tables, with ON specifying the fields that are equivalent (what you are JOINing ON). With that in mind:
SELECT s.salespersonNo, s.name, c.customerNo, cs.carNo,
cs.dateofsale, c.name, c.postCode
FROM salesperson s
INNER JOIN carsale cs
ON cs.salespersonNo = s.salespersonNo
INNER JOIN customer c
ON cs.customerNo = c.customerNo
WHERE cs.dateOfSale BETWEEN #01/09/2016# AND #02/09/2016#
ORDER BY CS.salespersonNo;
Notice that your WHERE and ORDER BY are unchanged, and I just used different aliases in my test run. The main difference is in the JOIN - I join from salesperson to CarSales ON the salespersonNo, and then from CarSales to customerNo, similar to what you already have.
The syntax error is because with multiple JOINs you need parentheses around every pair of them.
It would be a lot easier to use the query designer, it does those things automatically.
SELECT CS.carNo, CS.dateOfSale, SA.salespersonNo, SA.name AS SalesName,
CU.customerNo, CU.name AS CustName, CU.postCode
FROM (((CarSale AS CS
INNER JOIN Car AS C ON CS.carNo = C.carNo)
INNER JOIN Salesperson AS SA on CS.salespersonNo = SA.salespersonNo)
INNER JOIN Customer AS CU ON CS.customerNo = CU.customerNo)
WHERE cs.dateOfSale BETWEEN #01/09/2016# AND #02/09/2016#
ORDER BY CS.salespersonNo;
As Stidgeon wrote, if these are all fields you need, you can omit the join with Car.

SQL Joins with Five tables

I have a SQL Database containing five tables.
tblExpense : Expense_ID, Expense_Catagory, Expense_Date, Expense_Particular, Expense_Amount
tblExpenseTransaction : Expense_Transaction_ID, Expense_ID, Transaction_ID
tblStudentMain : Student_Main_ID, Student_Name
tblStudentTransaction : Student_Transaction_ID, Student_Main_ID, Transaction_ID
tblTransaction : Transaction_ID, Transaction_Date, Transaction_Amount
Now tblTransaction contains transactions done by students or expenses and are connected by between tables( i.e. tblStudentTransaction and tblExpenseTransaction). The Relations are like tblStudent -> tblStudentTransactions -> tblTransactions and tblExpense -> tblExpenseTransaction -> tblTransaction.
Now My Task is to retrieve all the transactions made only by Students or Expenses.
I tried to do that using this query :
SELECT tblTransaction.Transaction_ID, tblTransaction.Transaction_Date, tblTransaction.Transaction_Amount, tblTransaction.Transaction_Particular, tblTransaction.Transaction_Mode,
tblTransaction.Is_Deposit
FROM tblTransaction INNER JOIN
tblStudentTransaction ON tblTransaction.Transaction_ID = tblStudentTransaction.Transaction_ID INNER JOIN
tblStudentMain ON tblStudentTransaction.Student_Main_ID = tblStudentMain.Student_Main_ID
which gives me result. But when i tried to do that with other set of tables with this :
SELECT tblTransaction.Transaction_ID, tblTransaction.Transaction_Date, tblTransaction.Transaction_Amount, tblTransaction.Transaction_Particular, tblTransaction.Transaction_Mode,
tblTransaction.Is_Deposit
FROM tblTransaction INNER JOIN
tblExpenseTransaction ON tblTransaction.Transaction_ID = tblExpenseTransaction.Transaction_ID RIGHT OUTER JOIN
tblExpense ON tblExpenseTransaction.Expense_ID = tblExpense.Expense_ID
query returned rows with transactions related to student also.
Now i know that, i need to use RIGHT, LEFT or either JOIN but i am confused. Please give me idea if anyone have.
Assuming you need a single query that indicates if the transaction is associated with an expense, a student or neither:
SELECT t.*, CASE
WHEN e.Transaction_ID IS NOT NULL THEN 'Expense'
WHEN s.Transaction_ID IS NOT NULL THEN 'Student'
ELSE 'Other'
END AS Type
FROM tblTransaction t
LEFT JOIN tblExpenseTransaction e ON e.Transaction_ID = t.Transaction_ID
LEFT JOIN tblStudentTransaction s ON s.Transaction_ID = t.Transaction_ID
WHERE Type = 'Expense'
Or you could specify Type = 'Student`` to get all student-related transactions, orType = 'Other'` for others, or leave off the WHERE clause off to get all transactions and their type.
As per my understanding individually you are getting the records for the student and expense using the below queries thus try adding union to the two and you should get the requisite data.
As expense and student are individual entities thus I dont think there would be any overlapping / common records between the two tables thus inner join should work fine for you.
SELECT tblTransaction.Transaction_ID, tblTransaction.Transaction_Date, tblTransaction.Transaction_Amount,
tblTransaction.Transaction_Particular, tblTransaction.Transaction_Mode,
tblTransaction.Is_Deposit
FROM tblTransaction INNER JOIN
tblStudentTransaction ON tblTransaction.Transaction_ID = tblStudentTransaction.Transaction_ID INNER JOIN
tblStudentMain ON tblStudentTransaction.Student_Main_ID = tblStudentMain.Student_Main_ID
union
SELECT tblTransaction.Transaction_ID, tblTransaction.Transaction_Date, tblTransaction.Transaction_Amount,
tblTransaction.Transaction_Particular, tblTransaction.Transaction_Mode,
tblTransaction.Is_Deposit
FROM tblTransaction INNER JOIN
tblExpenseTransaction ON tblTransaction.Transaction_ID = tblExpenseTransaction.Transaction_ID INNER JOIN
tblExpense ON tblExpenseTransaction.Expense_ID = tblExpense.Expense_ID