SQL query with three level categories - sql

This problem has puzzled me a while and I hope there are some wiz that could help solve this problem. I have a product table with three level of categories (three tables). I'm trying to list all products that is connected to the last level(third level) of the categories. When running the query below ALL products in the product table is listed.
Here is the SQL query.
SELECT *
FROM Product
INNER JOIN Product_Category
ON Product.ProductCategoryID = Product_Category.ProductCategoryID
INNER JOIN Product_Sub_Category
ON Product_Category.ProductCategoryID = Product_Sub_Category.ProductCategoryID
INNER JOIN Product_Sub_Sub_Category
ON Product_Sub_Category.ProductSubCategoryID = Product_Sub_Sub_Category.ProductSubCategoryID
WHERE Product_Sub_Sub_Category.ProductSubSCategoryID = request.querystring

You need to join on SubCategoryId on the second level and SubSubCategoryId on the third level
SELECT *
FROM
Product
INNER JOIN Product_Category ON (Product.ProductCategoryID = Product_Category.ProductCategoryID)
INNER JOIN Product_Sub_Category ON (Product_Category.ProductSubCategoryID = Product_Sub_Category.ProductSubCategoryID)
INNER JOIN Product_Sub_Sub_Category ON (Product_Sub_Category.ProductSubSubCategoryID = Product_Sub_Sub_Category.ProductSubSubCategoryID)
WHERE
Product_Sub_Sub_Category.ProductSubSubCategoryID = (request.querystring)

Related

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

Complex SQL Code

I am having trouble with a SQL query that corresponds to multiple different tables. I have written the following code, but it seems to combine every single booking with every invoice rather than finding the specific invoice that matches a specific booking. Any help would be greatly appreciated.
$sql = "SELECT INVOICE.invoice_id,
g.guest_first_name,
g.guest_last_name,
g.booking_num_guests,
g.booking_num_nights,
CURRENCY.currency_name,
INVOICE.invoice_nightly_rate,
INVOICE.invoice_deposit_amount,
INVOICE.invoice_paid,
ACCOUNT.account_name
FROM INVOICE
INNER JOIN BOOKING
ON INVOICE.invoice_booking_id = BOOKING.booking_id
INNER JOIN CURRENCY
ON INVOICE.invoice_currency_id = CURRENCY.currency_id
INNER JOIN ACCOUNT
ON INVOICE.invoice_account_id = ACCOUNT.account_id
INNER JOIN (
SELECT GUEST.guest_first_name,
GUEST.guest_last_name,
BOOKING.booking_num_guests,
BOOKING.booking_num_nights
FROM BOOKING
INNER JOIN GUEST
ON BOOKING.booking_guest_id = GUEST.guest_id) g
ON INVOICE.invoice_booking_id = BOOKING.booking_id";
Since you already joined INVOICE and BOOKING table in the first inner join, the last inner join should be between BOOKING and GUEST table. Change your query to below
$sql = "SELECT
INVOICE.invoice_id,
GUEST.guest_first_name,
GUEST.guest_last_name,
BOOKING.booking_num_guests,
BOOKING.booking_num_nights,
CURRENCY.currency_name,
INVOICE.invoice_nightly_rate,
INVOICE.invoice_deposit_amount,
INVOICE.invoice_paid,
ACCOUNT.account_name
FROM INVOICE
INNER JOIN BOOKING
ON INVOICE.invoice_booking_id = BOOKING.booking_id
INNER JOIN CURRENCY
ON INVOICE.invoice_currency_id = CURRENCY.currency_id
INNER JOIN ACCOUNT
ON INVOICE.invoice_account_id = ACCOUNT.account_id
INNER JOIN GUEST
ON BOOKING.booking_guest_id = GUEST.guest_id";

Transferring data from different tables into dimension table

I am trying to fill my product dimension with data from AdventureWorks database using the following query
SELECT product.Class,
product.Color,
product.DaysToManufacture,
product.DiscontinuedDate,
product.ProductLine,
product.FinishedGoodsFlag,
product.ListPrice,
product.MakeFlag,
product.Name AS productName,
productDescription.[Description],
product.ProductNumber,
product.ReorderPoint,
product.SafetyStockLevel,
product.SellEndDate,
product.SellStartDate,
product.Size,
product.StandardCost,
product.Style,
product.[Weight],
model.Name AS model,
product.WeightUnitMeasureCode,
product.SizeUnitMeasureCode,
subcategory.Name AS subcategoryName,
category.Name AS categoryName,
photo.LargePhoto,
photo.LargePhotoFileName,
photo.ThumbNailPhoto,
photo.ThumbnailPhotoFileName
FROM AdventureWorks2008R2.Production.Product product
INNER JOIN AdventureWorks2008R2.Production.ProductModel model
ON (product.ProductModelID = model.ProductModelID)
INNER JOIN AdventureWorks2008R2.Production.ProductSubcategory subcategory
ON (subcategory.ProductSubcategoryID = product.ProductSubcategoryID)
INNER JOIN AdventureWorks2008R2.Production.ProductCategory category
ON (category.ProductCategoryID = subcategory.ProductCategoryID)
INNER JOIN AdventureWorks2008R2.Production.ProductProductPhoto productphoto
ON (productphoto.ProductID = product.ProductID)
INNER JOIN AdventureWorks2008R2.Production.ProductPhoto photo
ON (productphoto.ProductPhotoID = photo.ProductPhotoID)
INNER JOIN AdventureWorks2008R2.Production.ProductModelProductDescriptionCulture productModelDescription
ON (productModelDescription.ProductModelID = model.ProductModelID)
INNER JOIN AdventureWorks2008R2.Production.ProductDescription productDescription
ON (productModelDescription.ProductDescriptionID = productDescription.ProductDescriptionID)
WHERE productModelDescription.CultureID = 'en';
However there are 504 product records in Product tables, but this query yields only 294 records. After tracing the query for a while, I figured out that the joins to get product description is the reason for the deducted number of product records.
My question is how to get All product records (504) while getting product description information as well, if not found put NULL
You can use FULL OUTER JOIN with ProductDescription table.
.....
.....
INNER JOIN AdventureWorks2008R2.Production.ProductModelProductDescriptionCulture productModelDescription
ON (productModelDescription.ProductModelID = model.ProductModelID)
FULL OUTER JOIN AdventureWorks2008R2.Production.ProductDescription productDescription
.....
By using LEFT JOIN you will get all products. INNER JOIN will remove the once rows that do not match in your ON statement.
Edit: This image shows you the results from the different types of joins:
You can see there that by using INNER JOIN you only get the rows where both tables overlap, while using LEFT JOIN you will always return the full set of the first table.

Joining multiple tables and getting multiple attributes from one of them

I'm trying to join multiple tables together for building a report. The report lists a course, revisions made to it, and who requested, made and approved the revisions.
Under requested, made an approved, the values are employee numbers. I'm trying to join my innerjoined table above, with the Employee table so I can list the names (not just employee numbers) of those that requested, made and approved revisions.
This is what I have which I know is totally wrong.
SELECT *
FROM Courses
INNER JOIN CourseRevisions ON CourseRevisions.PELID = Courses.PELID
INNER JOIN CourseGroups ON CourseGroups.CourseGroupID = Courses.CourseGroupID
INNER JOIN [dbo].[OPG_Employees] ON OPG_Employees.EmployeeID = CourseRevisions.UpdatedBy
AND OPG_Employees.EmployeeID = CourseRevisions.ApprovedBy
AND OPG_Employees.EmployeeID = CourseRevisions.RequestedBy
This only returns a single result which just happens to have the same employee ID listed for all 3 (Requested, Approved and Updated)
How would i get it so I can get the table result for individual employees in each?
You have to join to the OPG_Employees table once for each field, i.e. 3 times in the example above. One INNER JOIN to it for UpdatedBy, one INNER JOIN for ApprovedBy, one INNER JOIN for RequestedBy.
Something like so:
SELECT *
FROM Courses
INNER JOIN CourseRevisions ON CourseRevisions.PELID = Courses.PELID
INNER JOIN CourseGroups ON CourseGroups.CourseGroupID = Courses.CourseGroupID
INNER JOIN [dbo].[OPG_Employees] empUpdatedBy ON empUpdatedBy.EmployeeID = CourseRevisions.UpdatedBy
INNER JOIN [dbo].[OPG_Employees] empApprovedBy ON empApprovedBy.EmployeeID = CourseRevisions.ApprovedBy
INNER JOIN [dbo].[OPG_Employees] empRequestedBy ON empRequestedBy.EmployeeID = CourseRevisions.RequestedBy
You need a separate join for each employee being referenced:
SELECT *
FROM Courses INNER JOIN
CourseRevisions
ON CourseRevisions.PELID = Courses.PELID INNER JOIN
CourseGroups
ON CourseGroups.CourseGroupID = Courses.CourseGroupID INNER JOIN
[dbo].[OPG_Employees] UpdateEmp
ON UpdateEmp.EmployeeID = CourseRevisions.UpdatedBy INNER JOIN
[dbo].[OPG_Employees] ApprovedEmp
on OPG_ApprovedEmp.EmployeeID = CourseRevisions.ApprovedBy INNER JOIN
[dbo].[OPG_Employees] RequestedEmp
on RequestedEmp.EmployeeID = CourseRevisions.RequestedBy
Your original formulation required that all three ids be exactly the same.

Get correct result from mysql query

I have the following tables:
**products** which has these fields: id,product,price,added_date
**products_to_categories** which has these fields: id,product_id,category_id
**adverts_to_categories** -> id,advert_id,category_id
**adverts** which has these fields: id,advert_name,added_date,location
I can not execute sql that will return to me all products that are from category 14 and that are owned by advert located in London. So I have 4 tables and 2 conditions - to be from category 14 and the owner of the product to be from London. I tried many variants to execute sql but none of the results were correct.. Do I need to use Join and which Join - left, right, full? How the correct sql will look like? thank you in advance for your help and sorry for boring you :)
This is what I have tried so far:
SELECT p.id, product, price, category_id,
p.added_date, adverts.location, adverts.id
FROM products p,
products_to_categories ptc,
adverts,
adverts_to_categories ac
WHERE ptc.category_id = "14"
AND ptc.product_id=p.id
AND ac.advert_id=adverts.id
AND adverts.location= "London"
pretty basic logic
Select * from Products P
INNER JOIN Products_To_Categories PTC ON P.ID = PTC.Product_ID
INNER JOIN Adverts_to_Categories ATC ON ATC.Category_Id = PTC.Category_ID
INNER JOIN Adverts AD on AD.ID = ATC.Advert_ID
WHERE PTC.Category_ID = 14 and AD.Location = 'LONDON'
you would only need a LEFT or right join IF you wanted records from a table which didn't exist in other tables.
so for example, if you wanted all products even if a records even those without a category, then you would use a LEFT Join instead of inner.
The following statement should return all columns from the product table in category with id 14 and all adverts located in London:
select p.* from products p
inner join products_to_categories pc on p.id = pc.product_id
inner join adverts_to_categories ac on pc.category_id = ac.category_id
inner join adverts a on a.id = ac.advert_id
where pc.category_id = 14
and ac.location = 'London';
You should remember to add an index to the column location if you are doing these string-based queries very often.