Transferring data from different tables into dimension table - sql

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.

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

Conditional statement to determine which table to Select from in Access 2013

I am trying to come up with a query to show the purchase and product information made by a member, and I was wondering if there is a way create a conditional statement to determine whether the product the member bought was from the Clothing table, Accessory table or if they bought a product from both tables. and the determining factor for which table is the ProductID in the Product table, if the user didn't but from the clothing table, the ProductID should be 0. The ProductID connects to both the Clothing and Accessory tables by their ProductTypeID, if you need any more information, let me know, thanks!
An image of the tables in Access is here
And here it is in SQL View
SELECT Member.MemberID, Member.FirstName, Member.LastName,
Purchase.PurchaseDate, LineItem.CalculatedPrice, Product.ProductType
FROM ClothingType
INNER JOIN ((AccessoryType INNER JOIN (((Member INNER JOIN Purchase
ON Member.MemberID = Purchase.MemberID)
INNER JOIN (Product INNER JOIN LineItem ON Product.ProductID = LineItem.ProductID)
ON Purchase.PurchaseID = LineItem.PurchaseID)
INNER JOIN Accessory ON Product.ProductID = Accessory.ProductTypeID)
ON AccessoryType.AccessoryTypeID = Accessory.AccessoryTypeID)
INNER JOIN Clothing ON Product.ProductID = Clothing.ProductTypeID)
ON ClothingType.ClothingTypeID = Clothing.ClothingTypeID;
you need to modify your query to use left joins. Unfortunately MS Access has its craziness about the parenthesis in the JOINS, so my query below may be erroneous. Please comment below if Access complains about errors in the JOIN clause, and I will do my best to fix it:
SELECT Member.MemberID, Member.FirstName, Member.LastName,
Purchase.PurchaseDate, LineItem.CalculatedPrice, Product.ProductType
FROM Member INNER JOIN (Purchase
INNER JOIN (Product INNER JOIN (LineItem
LEFT JOIN (Accessory LEFT JOIN (AccessoryType
LEFT JOIN (Clothing LEFT JOIN ClothingType ON
ClothingType.ClothingTypeID = Clothing.ClothingTypeID)
ON Product.ProductID = Clothing.ProductTypeID)
ON AccessoryType.AccessoryTypeID = Accessory.AccessoryTypeID)
ON Product.ProductID = Accessory.ProductTypeID)
ON Product.ProductID = LineItem.ProductID)
ON Purchase.PurchaseID = LineItem.PurchaseID)
ON Member.MemberID = Purchase.MemberID);
However, as I mentioned above, it may not work because of Access stupidity around its usage of JOINs. You may be better of to double-clicking on the last four join lines in the designer (to the right of Product) and make them all "Select all from the left table and only those that match from the right table" option (which is a LEFT JOIN in Access terms)
UPDATE: forgot to add: once you have your join working all you need to do is to use an expression for the Accessory/Clothing description like this:
Iif(IsNULL(AccessoryType.Description), ClothingType.Description, AccessoryType.Description) as Description

SQL query with three level categories

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)

SQL table joins

I am trying to use SQL to get results back from my database but I cannot get the query right.
Above is the entity descriptions from my database and I want to get back the information for the price of a product, the quantity, and the parts associated with it. The ProductParts table is a link table between Product and Part.
Here is the values in the ProductParts table and the result that I want back. I have tried using a cross join but I can't seem to get it correct, I keep getting results like this (below)
I am currently using this query
SELECT
Product.Price,
Product.Quantity,
kit_name.PartID as "Kit Name",
blank_name.PartID as "Blank Name"
FROM Product
CROSS JOIN ProductParts as kit_name
CROSS JOIN ProductParts as blank_name
WHERE Product.ProductID = 3
AND Product.ProductID = kit_name.ProductID
AND Product.ProductID = blank_name.ProductID
This is the result I get back
Try this one:
SELECT
Product.Price,
Product.Quantity,
p.PartID AS PartID,
FROM Product
INNER JOIN ProductParts as pp
ON pp.ProductId=Product.ProductId
INNER JOIN Parts as p
ON p.PartId=pp.PartId
WHERE Product.ProductID = 3
A simple inner join between ProductPart, Product and Part would work:
SELECT
prod.Price,
prod.Quantity,
prod.ProductId as "Kit Name",
part.PartID as "Blank Name"
FROM ProductParts pp
JOIN Product as prod
on pp.ProductId = prod.ProductId
JOIN Parts part
on pp.PartId = part.PartId
WHERE pp.ProductID = 3

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.