SQL query on link table where results must contain certain value - sql

SQL Server 2005.
I've a link table of Products and Attributes associated with them. I'm doing a search along the lines of:
select distinct ProductId from productattributelink where
attributeid in (25,5,44,46)
But I want to make sure that each productid is also associated with an attributeId of 10.
So in longhand the query would be: Show me all the product Ids that have the following attributeids (25,5,44,46) but also have attributeid of 10.
I've a feeling this is really obvious but is eluding me.

select distinct p.ProductId from product p
inner join productattributelink pa1 on pa1.ProductId = p.ProductId
inner join productattributelink pa2 on pa2.ProductId = p.ProductId
where pa1.attributeid IN(25,5,44,46) and pa2.attributeid = 10

You should join the table to itself:
select distinct ProductId from productattributelink p1
JOIN productattributelink p2 ON p1.ProductId = p2.ProductId
where p1.attributeid in (25,5,44,46) AND p2.attributeid = 10

Related

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

WHERE Clause for One-To-Many Association

I have two tables Products and ProductProperties.
Products
name - string
description - text
etc etc
ProductProperties
product_id - integer
property_id - integer
There is also a table Properties which basically stores the list of property names and their attributes
How can I implement a SQL command that finds a product with the property_ids (A or B or C) AND (X or Y or Z)
I've got upto here:
SELECT DISTINCT "products".*
FROM "products"
INNER JOIN "product_properties" ON "product_properties"."product_id" = "products"."id" AND "product_properties"."deleted_at" IS NULL
WHERE "products"."deleted_at" IS NULL
AND (product_properties.property_id IN ('504, 506, 403'))
AND (product_properties.property_id IN ('520, 501, 502'))
But it doesn't really work since it's looking for a Product Property which has both values 504 and 520, which will never exist.
Would appreciate some help!
You need to define intermediate resultsets on a property group basis:
SELECT DISTINCT p.*
FROM products p
JOIN product_properties groupA ON groupA.product_id = p.id AND groupA.deleted_at IS NULL AND groupA.property_id IN ('504')
JOIN product_properties groupB ON groupB.product_id = p.id AND groupB.deleted_at IS NULL AND groupB.property_id IN ('520')
WHERE p.deleted_at IS NULL
You see, you detected the problem yourself very nicely: "But it doesn't really work since it's looking for a Product Property which has both values 504 and 520, which will never exist."
Indeed, recordsets are immutable within a query, all single criteria applied to them are applied all at once. You need to duplicate each table and apply individual criteria to them.
One method uses exists or in:
select p.*
from products p
where p.id in (select pp.product_id
from product_properties pp
where pp.propertyid in ('504', '520')
);
This saves you from having to use distinct in the outer query.
If, perchance, you really mean finding the products that have all the properties, then a join and group by work:
select p.*
from products p join
product_properties pp
on p.id = pp.product_id
where pp.propertyid in ('504', '520')
group by p.id -- yes, this is allowed in Postgres
having count(*) = 2;
Hi try this queries i just thinking about it so i didn't try any of them check i got the idea i want to do
SELECT DISTINCT "products".*
FROM products pr
WHERE id IN
(
SELECT product_id FROM ProductProperties WHERE property_id IN (504,520)
GROUP BY product_id
HAVING Count(*) = 2
) AND "products"."deleted_at" IS NULL
SELECT DISTINCT "products".*
FROM products pr, INNER JOIN (
SELECT product_id,count(*) as nbr FROM ProductProperties WHERE property_id IN (504,520)
GROUP BY product_id
) as temp ON temp.product_id = pr.id
WHERE "products"."deleted_at" IS NULL AND temp.nbr = 2
and also you can check this one as well ( you can use also the join in where clause instead of using INNER JOIN)
SELECT DISTINCT products.* FROM products as p
INNER JOIN product_properties as p1 ON p1.product_id = p.id
INNER JOIN product_properties as p2 ON p2.product_id = p.id
WHERE p.deleted_at IS NULL
AND p1.property_id = '504' AND p1.deleted_at IS NULL
AND p2.property_id = '520' AND p2.deleted_at IS NULL

How to Select Data From Multiple Tables using inner join statment?

I have three tables
Products Table :
ID
GeneralStockEnabled
RetailerID
Sources Table
ID
Name
RetailerID
and
ProductInventory Table
ProductID
SourceID
Stock
The user will pass both the #RetailerID and #ProductID in my Stored Procedure.
How Can I select All the sources for particular retailer and attach the stock value coming from the product inventory table to those sources exists in the product inventory table for a particular product id and also select the value of GeneralStockEnabled for that product? . Even I my product has no stocks, I still want to be able to retrieve all the sources for that retailer?.
Any Help is appreciated.
I have this SQL right now :
SELECT S.ID AS SourceID,S.Name AS SourceName,PIN.Stock
FROM Sources S
LEFT OUTER JOIN ProductInventory PIN
ON (S.ID = PIN.SourceID)
WHERE S.RetailerID = 1
AND PIN.ProductID = 1
but since my product inventory table has no records now. It is not selecting the left part which are the sources in this case.
try something like this:
select s.*, pr.Stock, p.GeneralStockEnabled
from sources s join
Products p on s.RetailerId = p.RetailerId left outer join
ProductInventory pr on pr.ProductId = p.Id
where s.RetailerId = #RetailerId and p.id = #ProductId
You can use joins for the same
http://www.w3schools.com/sql/sql_join.asp

Join in Query WHERE clause

I have several tables I"m trying to get data out of efficiently.
I have a drafted query as such:
SELECT products.id, products.name products.extended_description, products.catalogid, products.image1, products.image2, products.stock, products.price, manufacturer.manufacturer, products.weight
FROM products
JOIN manufacturer ON (products.manufacturer = manufacturer.id)
WHERE category.category_name = ?;
Obviously this is a broken query, but I'm not sure how to fix this. I need to somehow join category table to product_category table which is related to products table via the products.catalogid field.
My feeble attempt is as such:
SELECT products.id, products.name products.extended_description, products.catalogid, products.image1, products.image2, products.stock, products.price, manufacturer.manufacturer, products.weight
FROM products
JOIN manufacturer ON (products.manufacturer = manufacturer.id)
FROM category
JOIN product_category ON (category.id = (SELECT product_category.id FROM product_category WHERE product_category.catalogid /*I'm so lost...*/))
WHERE category.category_name = ?;
Basically I need to query the db for all the info in the SELECT clause where the category name is "NEW"... and I'm completely stumped (my SQL obviously needs some work!)
Something like this, just keeping joining and joining and....
SELECT
*
FROM
products as p
JOIN
manufacturer as m
ON
p.manufacturer = m.id
JOIN
product_category as pc
ON
pc.product = p.id
JOIN
category as c
ON
c.id=pc.category
WHERE
c.name = "NEW"
Since you've got a product_category table, it appears that your product may belong to multiple categories. In cases like that, you want to check if a category that you are looking for is among the categories assigned to your product.
One way of doing it is with an EXISTS condition:
SELECT p.id, p.name p.extended_description, p.catalogid, p.image1, p.image2, p.stock, p.price, m.manufacturer, p.weight
FROM products p
JOIN manufacturer m ON (p.manufacturer = m.id)
WHERE
EXISTS (
SELECT *
FROM product_category pc
JOIN category c ON c.id=pc.categoryId
WHERE pc.productId = p.id
AND c.category.category_name = ?
)
I assumed that the product_category many-to-many table has columns categoryId and productId which bring together the IDs of the product and a category to which that product belongs.

SQL Selection of products in a single category

So here is what I am trying to do. My boss wants to put all vehicles that we have on our homepage and randomly pull 8 of them at a time. The way our database schema is setup has the products, and categories in separate tables using a cross reference to locate the category the product falls under. The table with the categories has a parent that is a direct ID from another category. So here is the SQL that I came up with.
SELECT product.productID,
product.productSKU,
product.price,
product.name,
product.stateInd,
category.parentID,
category.categoryID,
prod_cat.productID FROM category
LEFT JOIN prod_cat
ON prod_cat.categoryID = category.categoryID
LEFT JOIN product
ON product.productID = prod_cat.productID
WHERE category.parentID = <cfqueryparam value="#catID#" cfsqltype="cf_sql_varchar" /> AND product.name <> "" AND RAND()
LIMIT 8
I hope that all makes sense. I am just having the hardest time not only pulling 8 products but also making sure those 8 products are unique. Oh and I did try putting DISTINCT after the select but the product was still selected twice.
Thanks!
DISTINCT should work. If it doesn't, try to group by productId. To select random rows, order by rand() instead of the where rand() construct.
Combining the two:
WHERE category.parentID = <cfqueryparam value="#catID#" cfsqltype="cf_sql_varchar"/>
AND product.name <> ""
GROUP BY
product.productID
ORDER BY
RAND()
LIMIT 8
I'd pull the 8 unique products in a sub-query, then use that in the rest of your query.
In very rough pseudo-code:
select ...
from (select 8 distinct random product IDs from product table) p
left join prod_cat
on p.productID = prod_cat.productID
left join category
on prod_cat.categoryID = category.categoryID
...
NOTE: Joe beat me for this answer, but I was not sure how to put code in comment, so here is my answer.
I am not sure if categoryID will give single row or multiple rows for your input, if it is single row, you can very well use = instead of in
SELECT *
FROM (SELECT * FROM product
WHERE product.productID in (
SELECT productID
FROM prod_cat
WHERE categoryID in (
SELECT categoryID
FROM category
WHERE parentID =
<cfqueryparam
value="#catID#"
cfsqltype="cf_sql_varchar" />
)
AND name <> ''
ORDER BY rand()
LIMIT 8
) p
INNER JOIN prod_cat ON p.productID=prod_cat.productID
INNER JOIN category ON prod_cat.categoryID=category.categoryID