How to display duplicates of an aggregated attribute in Oracle SQL? - sql

I have a query, where I am finding the maximum weight of different products in a table. Each product has a brand name and a Sku, and each brand name can have multiple sku's.
That query is:
select brand_name
, sku
, max(weight)
from bc.PRODUCTS
group by BRAND_NAME, SKU
order by 1
I want to display only those brand_names who have return multiple rows in the above query.
My working query is:
select max(weight)
, sku
, brand_name
from bc.PRODUCTS
group by BRAND_NAME, sku
having count(brand_name) > 1
order by 3
;
Yet that does not return any results.
I am very much a beginner, so any help would be appreciated.
;

We can subquery your current query and include the count across each brand:
WITH cte AS (
SELECT BRAND_NAME, SKU, MAX(weight) AS MAX_WEIGHT,
SUM(COUNT(*)) OVER (PARTITION BY bra BRAND_NAME) cnt
FROM bc.PRODUCTS
GROUP BY BRAND_NAME, SKU
)
SELECT BRAND_NAME, SKU, MAX_WEIGHT
FROM cte
WHERE cnt > 1;

Related

SQL Query - second ID of a list ordered by date and ID

I have a SQL database with a list of Customer IDs CustomerID and invoices, the specific product purchased in each invoice ProductID, the Date and the Income of each invoice . I need to write a query that will retrieve for each product, which was the second customer who made a purchase
How do I do that?
EDIT:
I have come up with the following query:
SELECT *,
LEAD(CustomerID) OVER (ORDER BY ProductID, Date) AS 'Second Customer Who Made A Purchase'
FROM a
ORDER BY ProductID, Date ASC
However, this query presents multiple results for products that have more than two purchases. Can you advise?
SELECT a2.ProductID,
(
SELECT a1.CustomerID
FROM a a1
WHERE a1.ProductID = a2.ProductID
ORDER BY Date asc
LIMIT 1,1
) as SecondCustomer
FROM a a2
GROUP BY a2.ProductID
I need to write a query that will retrieve for each product, which was the second customer who made a purchase
This sounds like a window function:
select a.*
from (select a.*,
row_number() over (partition by productid order by date asc) as seqnum
from a
) a
where seqnum = 2;

The SUM of an aggregate COUNT function

I want to create a query to calculate the percentage sales of the overall policies in my database.
The policies are split under two separate headings
UL
NL
The code i want should display
product name
number of policies sold
policies sold per product as a percentage of the overall number of policies sold.
I have made a few attempts at scripting this code (please see below) but cannot get them to run correctly.
Syntax 1:
SELECT b.PRODUCT_NAME, b.POLICIES_SOLD, 100.00*(b.POLICIES_SOLD/SUM(b.POLICIES_SOLD)) AS'PERC_SALES'
FROM
(
SELECT a.PRODUCT_NAME, COUNT(a.PRODUCT_NAME) AS
'POLICIES_SOLD'
FROM
(SELECT PRODUCT_NAME FROM [ATLANTIS\jjudge].
[ALL_POLICIES_201706_NL]
UNION ALL
SELECT PRODUCT_NAME FROM [ATLANTIS\jjudge].
[ALL_POLICIES_201706_UL])a GROUP BY PRODUCT_NAME)b ;
Syntax 2:
SELECT a.PRODUCT_NAME, a.[POLICIES SOLD], 100.00*(a.[POLICIES SOLD]/SUM(a.[POLICIES SOLD]))
FROM
(SELECT PRODUCT_NAME, COUNT(*) AS 'POLICIES SOLD'FROM
[ATLANTIS\jjudge].[ALL_POLICIES_201706_NL] GROUP BY PRODUCT_NAME
UNION ALL
SELECT PRODUCT_NAME, COUNT(*) AS 'POLICIES SOLD' FROM
[ATLANTIS\jjudge].[ALL_POLICIES_201706_UL] GROUP BY
PRODUCT_NAME)a ;
Syntax 3:
SELECT b.PRODUCT_NAME, COUNT(b.PRODUCT_NAME) AS
'POLICIES_SOLD', 100.00*
(COUNT(b.PRODUCT_NAME)/SUM(SELECT(PRODUCT_NAME))
FROM
(SELECT COUNT(*) AS 'POLICY_COUNT' FROM [ATLANTIS\jjudge].[ALL_POLICIES_201706_NL]
UNION ALL
SELECT COUNT(*) AS 'POLICY_COUNT' FROM [ATLANTIS\jjudge].[ALL_POLICIES_201706_UL])a)) AS 'PERC_SALES'
FROM
(SELECT PRODUCT_NAME FROM [ATLANTIS\jjudge].
[ALL_POLICIES_201706_NL]
UNION ALL
SELECT PRODUCT_NAME FROM [ATLANTIS\jjudge].
[ALL_POLICIES_201706_UL])b GROUP BY PRODUCT_NAME;
I think you want a Window Function. Modify your Syntax 1 first line as:
SELECT
b.PRODUCT_NAME,
b.POLICIES_SOLD,
100.00*b.POLICIES_SOLD/SUM(b.POLICIES_SOLD) OVER () AS 'PERC_SALES'
You can do this using a single aggregation query with window functions:
SELECT p.PRODUCT_NAME, COUNT(*) AS POLICIES_SOLD,
COUNT(*) * 100.0 / SUM(COUNT(*)) OVER () as PERC_SALES
FROM ((SELECT PRODUCT_NAME
FROM [ATLANTIS\jjudge].[ALL_POLICIES_201706_NL]
) UNION ALL
(SELECT PRODUCT_NAME
FROM [ATLANTIS\jjudge].[ALL_POLICIES_201706_UL]
)
) p
GROUP BY PRODUCT_NAME;

SQL Select Group By Min() - but select other

I want to select the ID of the Table Products with the lowest Price Grouped By Product.
ID Product Price
1 123 10
2 123 11
3 234 20
4 234 21
Which by logic would look like this:
SELECT
ID,
Min(Price)
FROM
Products
GROUP BY
Product
But I don't want to select the Price itself, just the ID.
Resulting in
1
3
EDIT: The DBMSes used are Firebird and Filemaker
You didn't specify your DBMS, so this is ANSI standard SQL:
select id
from (
select id,
row_number() over (partition by product order by price) as rn
from orders
) t
where rn = 1
order by id;
If your DBMS doesn't support window functions, you can do that with joining against a derived table:
select o.id
from orders o
join (
select product,
min(price) as min_price
from orders
group by product
) t on t.product = o.product and t.min_price = o.price;
Note that this will return a slightly different result then the first solution: if the minimum price for a product occurs more then once, all those IDs will be returned. The first solution will only return one of them. If you don't want that, you need to group again in the outer query:
select min(o.id)
from orders o
join (
select product,
min(price) as min_price
from orders
group by product
) t on t.product = o.product and t.min_price = o.price
group by o.product;
SELECT ID
FROM Products as A
where price = ( select Min(Price)
from Products as B
where B.Product = A.Product )
GROUP BY id
This will show the ID, which in this case is 3.

SQL query for table with multiple keys?

I am sorry if this seems too easy but I was asked this question and I couldn't answer even after preparing SQL thoroughly :(. Can someone answer this?
There's a table - Seller id, product id, warehouse id, quantity of products at each warehouse for each product as per each seller.
We have to list the Product Ids with Seller Id who has highest number of products for that product and the total number of units he has for that product.
I think I got confused because there were 3 keys in the table.
It's not quite clear which DBMS you are using currently. The below should work if your DBMS support window functions.
You can find count of rows for each product and seller, rank each seller within each product using window function rank and then use filter to get only top ranked sellers in each product along with count of units.
select
product_id,
seller_id,
no_of_products
from (
select
product_id,
seller_id,
count(*) no_of_products,
rank() over (partition by product_id order by count(*) desc) rnk
from your_table
group by
product_id,
seller_id
) t where rnk = 1;
If window functions are not supported, you can use correlated query to achieve the same effect:
select
product_id,
seller_id,
count(*) no_of_products
from your_table a
group by
product_id,
seller_id
having count(*) = (
select max(cnt)
from (
select count(*) cnt
from your_table b
where b.product_id = a.product_id
group by seller_id
) t
);
Don't know why having id columns would mess you up... group by the right columns, sum up the totals and just return the first row:
select *
from (
select sellerid, productid, sum(quantity) as total_sold
from theres_a_table
group by sellerid, productid
) x
order by total_sold desc
fetch first 1 row only
If I do not think about optimization, straight forward answer is like this
select *
from
(
select seller_id, product_id, sum(product_qty) as seller_prod_qty
from your_table
group by seller_id, product_id
) spqo
inner join
(
select product_id, max(seller_prod_qty) as max_prod_qty
from
(
select seller_id, product_id, sum(product_qty) as seller_prod_qty
from your_table
group by seller_id, product_id
) spqi
group by product_id
) pmaxq
on spqo.product_id = pmaxq.product_id
and spqo.seller_prod_qty = pmaxq.max_prod_qty
both spqi (inner) and sqpo (outer) give you seller, product, sum of quantity across warehouses. pmaxq gives you max of each product again across warehouses, and then final inner join picks up sum of quantities if seller has highest (max) of the product (could be multiple sellers with the same quantity). I think this is the answer you are looking for. However, I'm sure query can be improved, since what I'm posting is the "conceptual" one :)

dependent SQL subquery returns too few rows

I have a list of sales for hundreds of brands by shop and I want to get the TOP 100 brands per shop by sales.
For some unknown reason, it returns only 99 brands per shop. (In the source table there are more than 900 brands per each shop.)
That's my query:
SELECT TOP (100) PERCENT SHOP, BRAND, SALES
FROM dbo.[DATA] AS D
WHERE (BRAND IN
(SELECT TOP (100) WITH TIES BRAND
FROM DATA
WHERE (SHOP= D.SHOP)
ORDER BY SALES DESC
)
)
ORDER BY BRAND, SALES DESC
What went wrong?
I think what you are trying to do can be achieved by the following query
SELECT Q.SHOP
, Q.BRAND
, Q.SALES
FROM (
SELECT SHOP
, BRAND
, SALES
, ROW_NUMBER() OVER (PARTITION BY SHOP ORDER BY SALES DESC) rn
FROM dbo.[DATA]
) Q
WHERE Q.rn <= 100
ORDER BY Q.BRAND, Q.SALES DESC