I want to find the difference (the Profit & Loss) when I combine records with the same CATEGORY value (e.g. A's will be combined and C's will be combined).
I think you want conditional aggregation:
select category,
sum(iif(side = "BUY", - quantity * price, quantity * price)) as net
from t
where side in ("BUY", "SELL") -- may not be necessary
group by category;
Select category, buy.amt-sell.amt ProfitorLoss
from
(SELECT sum(price*quantity) amt, Category
FROM yourtable
WHERE side = 'BUY'
GROUP BY Category) buy,
(SELECT sum(price*quantity) amt, Category
FROM yourtable
WHERE side = 'SELL'
GROUP BY Category) sell
where buy.category = sell.category
Related
Most Expensive And Cheapest Wine
I'm trying to solve this question from Stratascratch, following the hint was given on the platform.
Find the cheapest and the most expensive variety in each region. Output the region along with the corresponding most expensive and the cheapest variety.
Please help review my answer and would love to know the better way to solve this.
SELECT EX.region_1, EX.expensive_variety, CH.cheap_variety
FROM
(SELECT A.region_1, A.expensive_variety
FROM
(SELECT distinct region_1, variety AS expensive_variety, price,
ROW_NUMBER() OVER (PARTITION BY region_1 ORDER BY price desc) as
most_expensive
FROM winemag_p1
ORDER BY region_1 asc) A
WHERE A.most_expensive = 1) EX
INNER JOIN
(SELECT B.region_1, B.cheap_variety
FROM
(SELECT distinct region_1, variety as cheap_variety, price,
ROW_NUMBER() OVER (PARTITION BY region_1 ORDER BY price ASC) as cheapest
FROM winemag_p1
ORDER BY region_1 asc) B
WHERE B.cheapest = 1) CH
ON EX.region_1 = CH.region_1
Something like this, the MIN and MAX per region:
SELECT region
, MIN(price) AS cheapest
, MAX(price) AS most_expensive
FROM table_name
GROUP BY region;
You can find both in the same sub-query.
SELECT
B.region_1,
MAX(CASE WHEN cheapest = 1 then variety else '' end) cheapest_variety,
MAX(CASE WHEN cheapest = 1 then price else 0 end) cheapest_price,
MAX(CASE WHEN expensive = 1 then variety else '' end) expensive_variety,
MAX(CASE WHEN expensive = 1 then price else 0 end) expensive_price
FROM
(SELECT distinct region_1, variety as cheap_variety, price,
ROW_NUMBER() OVER (PARTITION BY region_1 ORDER BY price ASC) as cheapest,
ROW_NUMBER() OVER (PARTITION BY region_1 ORDER BY price DESC) as expensive
FROM winemag_p1
) B
WHERE cheapest = 1 OR expensive = 1
GROUP BY region_1
ORDER BY region_1;
``
You can use window functions or subqueries to get the highest and lowest prices per region. Then get all rows with these prices and aggregate per region.
For instance:
select
region_1,
min(price) as low_price,
string_agg(variety, ', ') filter (where price = min_price) as low_price_varieties,
max(price) as high_price,
string_agg(variety, ', ') filter (where price = max_price) as high_price_varieties
from
(
select
region_1, variety, price,
min(price) over (partition by region_1) as min_price,
max(price) over (partition by region_1) as max_price
from winemag_p1
) with_min_and_max
where price in (min_price, max_price)
group by region_1
order by region_1;
As to your own query: This is an okay query. Here are my remarks:
ORDER BY in a subquery only makes sense, when limiting the rows (with FETCH FIRST ROWS), because a query result is an unordered data set by definition.
Why DISTINCT? There are no duplicates to remove.
You don't handle ties. If there are two top wines with the same price in a region for instance, you pick one arbirarily.
I am trying to find the top seller here. I was trying to use the below but i dont think this is right. I can see other ids that have bigger totals plus i think i should be using a SUM function instead of MAX.
select selleruserid
from sales_fact
where price = (select max(price) from sales_fact)
As I understand it you want to get the total sales of each seller and choose the seller who has the most sales.
The seller who has the most sales:
SELECT max(totalPrice) as totalPrice,selleruserid
FROM (SELECT sum(price) AS totalPrice,selleruserid FROM sales_fact GROUP BY selleruserid)
Total sales of each seller:
SELECT totalPrice as totalPrice,selleruserid
FROM (SELECT sum(price) AS totalPrice,selleruserid FROM sales_fact GROUP BY selleruserid)
You can use FETCH clause with TIES option as follows:
select selleruserid, sum(price) as total
from sales_fact
group by selleruserid
order by sum(price) desc
FETCH FIRST 1 ROW WITH TIES
OR You can use the analytical function RANK as follows:
select selleruserid, total from
(select selleruserid, sum(price) as total,
RANK() OVER (ORDER BY sum(price) DESC) AS rn
from sales_fact
group by selleruserid) t
where rn = 1
I have to use only single SELECT statement. Multiple select statements are not allowed.
I have a table named "Transactions" which has the following variables:
Qty - It has total Quantities ordered for a particular product
total_amt - It has Amount paid by customers for the particular products
Store_type - It has transaction channels
For example, if Qty ordered are 5 and price of each quantity of product is 100. then total_amt would be carrying 500.
Now I have to find the Store type that sells the maximum products by the value of sales amount & by quantity sold. I have to do this using sub queries in Having clause.
I have written the following code in SQL Server but it is not giving me any output and throwing the error that Transactions.total_amt should be included in having clause or aggregated function. On using total_amt in group by, I am not getting any result in the output.
Below is the query which I have written :
select store_type, MAX(total_amt), MAX(Qty)
from Transactions
group by Store_type
Having total_amt = (select SUM(total_amt) from Transactions group by Store_type)
AND
Qty = (select SUM(Qty) from Transactions group by Store_type)
A simple way is based on max order by and limit
select store_type, MAX(total_amt), MAX(Qty)
from Transactions
group by Store_type
ORDER BY MAX(total_amt) DESC, MAX(Qty) DESC
LIMIT 1
Check both query result and identify store type wise total amt and max total amt matching with qty or not.
If you want only matched then you can create 2 sub query tables and use inner join.
I hope this will resolve.
select
Store_type,
SUM(total_amt) AS Total_total_amt,
SUM(Qty) AS Total_Qty
from Transactions
group by Store_type
select
store_type,
MAX(total_amt) AS max_total_amt,
MAX(Qty) AS max_Qty
from Transactions
group by Store_type
You can use a query as shown below
;With cte as
(
Select sum(qty) as sum_quantity,sum(sales) as sum_sales,store_type
From transaction
Group by store_type
)
Select Max(sum_quantity),max(sum_sales),store_type from cte
Group by store_type
Select store_type
From transactions
Where total_amt > 0 and qty>0
Group by store_type
Order by sum(total_amt) desc,sum(qty) desc ;
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 :)
I'd like to select each pair of two columns in a database, but only select the entry with the lowest price. As a result, I want to output the id and the price column.
But it does not work:
My table:
id | category | type | name | price
1;"car";"pkw";"honda";1000.00
2;"car";"pkw";"bmw";2000.00
SQL:
select min(price) price, id
from cartable
group by category, type
Result:
Column "cartable.id" must be present in GROUP-BY clause or used in an aggregate function.
If you want the entry with the lowest price, then calculate the lowest price and join the information back in:
select ct.*
from cartable ct join
(select category, type, min(price) as price
from cartable
group by category, type
) ctp
on ct.category = ctp.category and ct.type = ctp.type and ct.price = ctp.price;
You can achieve this with EXISTS clause:
SELECT *
FROM cartable ct
WHERE
NOT EXISTS (
SELECT *
FROM cartable
WHERE ct.type = type and ct.category = categoery and ct.price < price)
For speed caparison can you try this:
SELECT DISTINCT ON (type, category), id, price
FROM cartable
ORDER BY price DESC
SELECT id, price
from cartable C
inner join
(
select min(price) as price , category, type
from cartable
group by category, type
)T
on T.category = C.category
and T.type = C.type
Most of the time you can't do much else than resolve to use Select - Over
select price, id
from(
select price, id, [rnk] = ROW_NUMBER() over( partition by category, type order by price)
from cartable
) as a
where [rnk]=1
Create index appropriately and performance are good.
In your example something like this:
CREATE NONCLUSTERED INDEX [foo]
ON [dbo].[cartable] ([category],[type])
INCLUDE ([price])
Maybe you can try:
select id, price from cartable
where price = (select min(price) from cartable);