table stores has two columns like store_id and products. Write a SQL query to find store_ids which sell only shampoo and biscuit - sql

Store should sell only two products and that too only shampoo and biscuit
For example
Output:
my query: -
SELECT *
FROM (SELECT store_id AS gp_str
FROM (SELECT store_id,
COUNT(product) AS prd_cnt
FROM stores
GROUP BY store_id) x
WHERE x.prd_cnt = 2) y
LEFT JOIN stores ON y.gp_str = stores.store_id;
My query gave me result of stores which sell only two products but I wanted stores which sell two products which are shampoo and biscuit only.

SELECT store_id
FROM stores
GROUP BY store_id
HAVING COUNT(DISTINCT product) = 2
AND COUNT(*) = SUM(CASE WHEN product IN ('shampoo','biscuit') THEN 1 ELSE 0 END);

Related

How to calculate benefit of some specific product type in SQL Server?

So, here are my tables:
Sales
id
product_code
1
4536
2
4674
Products
product_code
product_name
price
real_price
4536
Red bull energy drink 300 ml
3,68
2,88
4674
Mac coffee 25 gr
2,59
2,10
I need to calculate how much benefit did I get from the products which have "Red Bull" in its name. Benefit is equal to price-real_price.
Expected output:
product_name
benefit
Red bull energy drink 300 ml
4536,4
Here is what I tried:
SELECT products.product_code,(price-real_price) as profit
FROM products
INNER JOIN sales
ON products.product_code = sales.product_code
outer apply (select count(*)
from sales as benefit
where product_name like '%red bull';
But it does not give me the output I want to get.
create table Sales (
id int,
product_code int)
create table Products(
product_code int,
product_name char(100),
price smallmoney,
real_price smallmoney)
insert into Sales values
(1, 4536),
(2, 4674),
(3, 4536) -- to have multiple sales for Red Bull
insert into Products values
(4536, 'Red bull energy drink 300 ml', 3.68, 2.88),
(4674, 'Mac coffee 25 gr', 2.59, 2.10)
select
p.product_name, sum(p.price - p.real_price) benefit
from Sales s join Products p on s.product_code = p.product_code
group by p.product_name
product_name
benefit
Mac coffee 25 gr
0.4900
Red bull energy drink 300 ml
1.6000
As you say that each line is one quantity sold the following query will do the job.
I suggest that it would be better to have a quantity column in the sales table.
select
p.product_code,
p.product_name,
count(s.product_code) as quantity_sold,
sum( (p.price-p.real_price)*count(s.product_code) as total_profit
from products p
join sales s on s.product_code = p.product_code
where p.product_name like '%red bull'
group by
p.product_code,
p.product_name;

Calculating multiple averages across different parts of the table?

I have the following transactions table:
customer_id purchase_date product category department quantity store_id
1 2020-10-01 Kit Kat Candy Food 2 store_A
1 2020-10-01 Snickers Candy Food 1 store_A
1 2020-10-01 Snickers Candy Food 1 store_A
2 2020-10-01 Snickers Candy Food 2 store_A
2 2020-10-01 Baguette Bread Food 5 store_A
2 2020-10-01 iPhone Cell phones Electronics 2 store_A
3 2020-10-01 Sony PS5 Games Electronics 1 store_A
I would like to calculate the average number of products purchased (for each product in the table). I'm also looking to calculate averages across each category and each department by accounting for all products within the same category or department respectively. Care should be taken to divide over unique customers AND the product quantity being greater than 0 (a 0 quantity indicates a refund, and should not be accounted for).
So basically, the output table would like below:
...where store_id and average_level_type are partition columns.
Is there a way to achieve this in a single pass over the transactions table? or do I need to break down my approach into multiple steps?
Thanks!
How about using “union all” as below -
Select store_id, 'product' as average_level_type,product as id, sum(quantity) as total_quantity,
Count(distinct customer_id) as unique_customer_count, sum(quantity)/count(distinct customer_id) as average
from transactions
where quantity > 0
group by store_id,product
Union all
Select store_id, 'category' as average_level_type, category as id, sum(quantity) as total_quantity,
Count(distinct customer_id) as unique_customer_count, sum(quantity)/count(distinct customer_id) as average
from transactions
where quantity > 0
group by store_id,category
Union all
Select store_id, 'department' as average_level_type,department as id, sum(quantity) as total_quantity,
Count(distinct customer_id) as unique_customer_count, sum(quantity)/count(distinct customer_id) as average
from transactions
where quantity > 0
group by store_id,department;
If you want to avoid using union all in that case you can use something like rollup() or group by grouping sets() to achieve the same but the query would be a little more complicated to get the output in the exact format which you have shown in the question.
EDIT : Below is how you can use grouping sets to get the same output -
Select store_id,
case when G_ID = 3 then 'product'
when G_ID = 5 then 'category'
when G_ID = 6 then 'department' end As average_level_type,
case when G_ID = 3 then product
when G_ID = 5 then category
when G_ID = 6 then department end As id,
total_quantity,
unique_customer_count,
average
from
(select store_id, product, category, department, sum(quantity) as total_quantity, Count(distinct customer_id) as unique_customer_count, sum(quantity)/count(distinct customer_id) as average, GROUPING__ID As G_ID
from transactions
group by store_id,product,category,department
grouping sets((store_id,product),(store_id,category),(store_id,department))
) Tab
order by 2
;

how to calculate Sum for two different table with different containing table field

I have two table "tbl_In_Details" and "tbl_Out_Details"
Sample data for tbl_In_Details
ID Item_Name Rate Quantity Source_company
1 wire 10 4 2020-04-21 22:47:29.083
2 Tea 4 20 2020-04-21 22:47:52.823
Sample data for tbl_Out_Details
ID Item_Name Quantity Created_Date
1 wire 1 2020-04-21 22:48:48.233
2 wire 2 2020-04-21 22:50:16.367
3 Tea 2 2020-04-21 23:48:39.943
Now i want to calculate SUM of price and price (RATE*QUANTITY) from out going table
i tried in such a way but not getting result
select o.Item_Name, SUM(o.quantity) as Total_quantity ,SUM(o.quantity * i.Rate) as Expenses
from tbl_In_Details i inner join tbl_Out_Details o
ON i.Item_Name = o.Item_Name group by o.Item_Name,o.quantity, i.Rate
My Output should be
Item_Name Total_quantity Expenses
Tea 2 8
wire 3 30
Your query is completely fine. The only thing you need to get the desired result is to delete grouping by 'quantity' and 'rate'.
select o.Item_Name, SUM(o.quantity) as Total_quantity ,SUM(o.quantity * i.Rate) as Expenses
from tbl_In_Details i inner join tbl_Out_Details o
ON i.Item_Name = o.Item_Name group by o.Item_Name;
One method uses union all and group by:
Aggregate before joining:
select i.item_name, o.quantity, i.expenses
from (select id, item_name, sum(rate*quantity) as expenses
from tbl_In_Details
group by id, item_name
) i join
(select id, item_name, sum(quantity) as quantity
from tbl_Out_Details
group by id, item_name
) o
on i.id = o.id

Displaying results for fixed values in SQL

I am having difficulty in solving the below problem:
I have a table which contains the shopid, date, hour, category and sales amount.
shopid date hour category amount
------------------------------------
1 date1 7 food 10
1 date1 8 food 15
1 date1 10 misc. 5
2 date1 7 food 6
...................................
I am trying to calculate the total sales amount in each hour by food category and display like the following:
shopid category hour amount
------------------------------------
1 food 6 0
1 food 7 5
1 food 8 20
2 food 9 40
...................................
The shops' opening hours are 6 am -10 pm. So for each hour, there might be any sales or not. I was able to perform the hourly summation. But I am unable to display zero and the time when there are no sales at a particular time (e.g. 6 am or any other time between the opening hours) for each sale category.
Use a left join against a list of hours:
select t.shopid, t.category. g.hour, sum(t.amount)
from generate_series(6,22) as g(hour)
left join the_table t on t.hour = g.hour
group by t.shopid, t.category, g.hour
order by t.shopid, t.category, g.hour;
I am trying to calculate the total sales amount in each hour by food category.
This makes sense, but it doesn't make sense to include the shopid in the results.
To do this, you need to generate the rows -- which are all hours and food categories. Then bring in the actual results using left join:
select c.category. g.hour, coalesce(sum(s.amount), 0)
from generate_series(6, 22) g(hour) cross join
(select distinct category from sales) c left join
sales s
on s.hour = g.hour and s.category = c.category
group by c.category, g.hour
order by c.category, g.hour;
If you want results by shop/category/hour, then you can use the same idea:
select sh.shopid, c.category. g.hour,
coalesce(sum(s.amount), 0)
from generate_series(6, 22) g(hour) cross join
(select distinct category from sales) c cross join
(select distinct shopid from sales) sh left join
sales s
on s.shopid = sh.shopid and
s.hour = g.hour and
s.category = c.category
group by sh.shopid, c.category, g.hour
order by sh.shopid, c.category, g.hour;

SQL Sum of count across 3 tables

Say you have 3 tables:
Categories
Category ID
Name
Products
Product ID
Category ID (FK)
Sales
Product ID (FK)
Sale date
I'm trying to come up with a query that will result in a data table that shows the total number of sales per category, like:
Cat ID | Name | Total Sales
-------|------|-------------
1 | Red | 35
2 | Blue | 25
For bonus points, add a WHERE clause to select within a specific date range on the 'Sale Date' column.
I'm using SQL Server.
For SQL-Server could be something like that:
SELECT c.CategoryID AS [Cat ID],
c.Name AS [Name],
COUNT(s.ProductID) AS [Total Sales]
FROM Categories c
LEFT JOIN Products p
ON c.CategoryID = p.CategoryID
LEFT JOIN Sales s
ON p.ProductID = s.ProductID
WHERE s.Saledate BETWEEEN startDate and endDate
GROUP BY c.CategoryID, c.Name
select Categories.CatID, Categories.Name, count(*) as TotalSales
from Categories
join Products ON Categories.CategoryID = Products.CategoryID
join Sales ON Products.ProductID = Sales.ProductID
WHERE Sales.Saledate BETWEEEN date1 and date2
GROUP BY Categories.CatID, Categories.Name