Query to See Count of ProductName against same ProductId - sql

How to write Sql Query to show Number of Names based on one Product Id.
For example in this example: For ProductId - 263, Count(Name) = 3
I would like to see
263 3
264 2
265 10
266 0 (if null)

SELECT productid, COUNT(*)
FROM products
GROUP BY productid
It's not an exact answer, but it will return the number of occurrences of the productid for each unique productid. It may help you find your result.

Assuming you have a table of products, then you want a left join:
select p.productid, count(pn.productid)
from products p left join
productnames pn
on p.productid = pn.productid
group by p.productid;

Pang.
I have written an answer using a CTE that will give you the count of all the names for each product that can easily be changed to COUNT the DISTINCT names.
;WITH CTE_DISTINCT_NAMES
AS (SELECT --DISTINCT
/* Uncomment "DISTINCT" above
to include duplicate names
in the COUNT
*/
ProductId
, Name
FROM TABLE1
)
SELECT T.ProductId
, COUNT(ISNULL(T.Name,'')) AS [COUNT(Name)]
FROM CTE_DISTINCT_NAMES AS T
GROUP BY T.ProductId

Try this solution:
SELECT
PRODUCT_ID AS PID,
COALESCE(COUNT(NAME), 0) AS CNT
FROM YOUR_TABLE
GROUP BY PRODUCT_ID

Related

How to count a foreign key and use it to sort the primary table?

I have 2 tables:
Product (prod_id, prod_name, vend_id)
Vendor (vend_id, vend_name, vend_state)
I am trying to make a query that will give me a list of the vend_name for every vendor that supplied only one product. vend_id is a foreign key in Product, and I would like to count how many instances of each vend_id are in Product and then list out the vend_name of those that only occur once. Any help would be appreciated.
I am using Oracle SQL Developer (because I have to).
This is what I have, but keep getting either "invalid identifier" or "group function is not allowed here"
select count(*), Product.vend_id, Vendor.vend_id
from Product
inner join Vendor on Product.vend_id = vend.vend_id
where count(*) < 2
group by product.vend_id, vendor.vend_name;
Something like this should work:
SELECT vend_name
FROM Vendor
WHERE vend_id IN (
SELECT vend_id
FROM Product
GROUP BY vend_id
HAVING COUNT(DISTINCT product_id) = 1
)
;
If you want to select the Vendors that have only one Product the query is similary to:
select Vend_id, count(*) as Tot_Products
from Product
group by Vend_id
having count(*) = 1
I advise you to lear the function GROUP BY... HAVING, with this you can write a condition on a column calcolata (like the result of a MAX, MIN and all the other functions) whitout use a nasted query like:
select *
from (select Vend_id, count(*) as Tot_Products
from Product
group by Vend_id)
where Tot_Products = 1
Now you have the Id for each Vendors that have only one Product, now you can get all information of vendors with a join on Vendors, do you have something like this:
SELECT V.Vend_name
FROM ( select Vend_id
from Product
having count(*) = 1
group by Vend_id )as P
inner join Vendors as V
on p.Vend_id = V.Vend_id

SQL select all rows have the same value

I would like to show all rows that have the same product no from the product table. I try this code but I got the error
00000 - "column ambiguously defined"
WITH cte AS(
SELECT product_no
FROM product
GROUP BY product_no
HAVING COUNT(*) > 1)
select * from product v
inner join cte on cte.product_no = v.product_no
where
ACCOUNTING_GROUP not in ('1000','1200')
The result I would like to have:
Product_no produc_Descrip ACCOUNTING_GROUP acc_group_descr
123 bike 1001 semi-finish-A
123 bike 1002 semi-finish-B
1234 motor 1005 ........
1234 motor 1006 ........
.... ....... .... ........
I'm not sure about my answer because some information are missing, we don't know the structure of table product but what I can see is that you are joining on "cte.PART_NO" and this field is not defined or selected in your with clause "SELECT product_no".
You might try something like
SELECT PART_NO, COUNT(1) FROM product
GROUP BY PART_NO
HAVING COUNT(1) > 1)
But in order to provide a better answer we need the structure of your table with some examples of data inserted and result expected. At the moment you select "*" and expect 2 columns as result which also seem ambiguous.
Currently, your query select all product that aren't in group 1000 or 1200 and that appears 2 times or more in the table product, is that what you are really looking for ?
Assuming you have a unique column such as accounting_group, I would just use exists:
select p.*
from products p
where exists (select 1
from products p2
where p2.product_no = p.product_no and
p2.accounting_group <> p.accounting_group
)
order by p.product_no;
If this is not the case, go for window functions:
select p.*
from (select p.*, count(*) over (partition by product_no) as cnt
from product p
) p
where cnt >= 2
order by product_no;
for what you're trying to accomplish I'd probably change the query a bit,
with CTE as (SELECT PRODUCT_NO
FROM PRODUCT
GROUP BY PRODUCT_NO
HAVING COUNT(*) >1)
SELECT PRODUCT_NO, produc_descrip, ACCOUNTING_GROUP, acc_group_descr
FROM PRODUCT V
WHERE PRODUCT_NO IN(SELECT PRODUCT_NO FROM CTE)
AND ACCOUNT_GROUP NOT IN('1000','1200');
Though honestly, I don't think you need to use a with statement here, you could have simply used a nested query to accomplish the same thing.
Here is an optimized version, you can try.
SELECT * FROM PRODUCTS P
JOIN (SELECT PRODUCT_NO FROM PRODUCTS WHERE ACCOUNTING_GROUP NOT IN ('1000','1200') GROUP BY PRODUCT_NO HAVING COUNT(*) > 1 )TEMP
ON P.PRODUCT_NO = TEMP.PRODUCT_NO

SQL query can't use variable in FROM statement

I'm new to SQL, so sorry for maybe stupid question.
Table will be from this SQL sandbox:
https://www.w3schools.com/sql/trysql.asp?filename=trysql_asc
There is table of format
OrderDetailID OrderID ProductID Quantity
1 10248 11 12
2 10248 42 10
3 10248 72 5
4 10249 14 9
5 10249 51 40
I want to get products with maximum average quantity.
I can get this using the following query:
SELECT avg.ProductID, avg.Quantity
FROM (
SELECT ProductID, AVG(Quantity) Quantity
FROM OrderDetails
GROUP BY ProductID
) avg
WHERE avg.Quantity = (
SELECT MAX(Quantity) FROM (
SELECT ProductID, AVG(Quantity) Quantity
FROM OrderDetails
GROUP BY ProductID
)
)
ProductID Quantity
8 70
48 70
Here I twice use block
SELECT ProductID, AVG(Quantity) Quantity
FROM OrderDetails
GROUP BY ProductID
because if I use query with avg instead of second block
SELECT avg.ProductID, avg.Quantity
FROM (
SELECT ProductID, AVG(Quantity) Quantity
FROM OrderDetails
GROUP BY ProductID
) avg
WHERE avg.Quantity = (SELECT MAX(Quantity) FROM avg)
I get error could not prepare statement (1 no such table: avg)
So my question is:
Is it a kind of syntaxis mistake and could be simply corrected, or for some reason I can't use variables like that?
Is there simplier way to make the query I need?
Consider Common Table Expressions (CTE) using WITH clause which allows you to avoid repeating and re-calculating the aggregate subquery. Most RDBMS's supports CTEs (fully valid in your SQL TryIt linked page).
WITH avg AS (
SELECT ProductID, AVG(Quantity) Quantity
FROM OrderDetails
GROUP BY ProductID
)
SELECT avg.ProductID, avg.Quantity
FROM avg
WHERE avg.Quantity = (
SELECT MAX(Quantity) FROM avg
)
This is not really a syntax thing, this is rather scope: you try to
reference an alias where it is not in a parent-child relationship. Only this way they can reference each other. (The identifier there is an alias not a variable - that's a different thing.)
A simpler way is to create a temporary set before you run the filter condition - as in a previous answer, with a CTE, or you can try with a temp table. These can be used anywhere because their scope is not within a subquery.

How to Count Items that are return by a Group By Statements

Im currently trying to create a query in SQL that groups a list of products by vendor ID and then by categoryID an returns the groups that only have more than one product listed in them.
This is what I have so far:
SELECT Product.VendorID, CategoryID, Count (*) as NumProducts, avg(ProductPrice) as AveragePrice
From Product, Vendor
Where ProductPrice>50
Group By Product.VendorID, CategoryID
Having Count (Product.ProductID)>1;
My problem is that it returns categories that also have only one item in them.
You would seem to need a join. My guess is:
SELECT Product.VendorID, CategoryID, Count(*) as NumProducts, avg(ProductPrice) as AveragePrice
From Product inner join
Vendor
on Product.VendorId = Vendor.VendorId
Where ProductPrice>50
Group By Product.VendorID, CategoryID
Having Count(*) > 1;
It is not clear where the columns are coming from in your query, but you may not need the Vendor table at all.

Finding Duplicates via Query in Access

In my table I have a number of products. It's come to my attention that someone has uploaded some products using the same code. How can I run a query that will find all rows that are NOT unique in the productno field?
As I understand the question, you want to see which rows include duplicate productno values, not just which productno values are duplicated.
If that's correct, select the duplicate productno values in a subquery and join your table to the subquery.
SELECT y.*
FROM
[Your Table] AS y
INNER JOIN
(
SELECT [productno], Count(*)
FROM [Your Table]
GROUP BY [productno]
HAVING Count(*) > 1
) AS sub
ON y.[productno] = sub.[productno]
ORDER BY y.[productno];
Try this
SELECT productno, count(*) as num FROM Products GROUP BY ProductNo HAVING count(*) > 1