SQL SUM with Conditions - sql

+--------+--------+-------+-------+
| PartId | ItemId | Price | Staus |
+--------+--------+-------+-------+
| 94669 | 3678 | 88 | 1 |
| 94669 | 3679 | 22 | 1 |
| 94669 | 3680 | 30 | 1 |
| 94669 | 3681 | 50 | 4 |
| 94670 | 3678 | 88 | 1 |
| 94670 | 3679 | 22 | 1 |
| 94670 | 3680 | 30 | 1 |
| 94670 | 3681 | 50 | 1 |
+--------+--------+-------+-------+
The expected output is (without status 4)
+--------+------------+
| PartId | TotalPrice |
+--------+------------+
| 94669 | 140 |
| 94670 | 190 |
+--------+------------+
How can I achieve this in SQL?

Pretty basic aggregation query with a where and group by.
select partid, sum(price) as totalprice
from t
where [status] <> 4
group by partid
If you have to omit status other than 1, it would be correct to use status = 1 instead:
select partid, sum(price) as totalprice
from t
where [status] = 1
group by partid

You can try:
SELECT "Part ID", SUM(Price)
FROM (
SELECT "Part ID", Price
FROM Table
WHERE Status <> 4)
GROUP BY "Part ID";

Related

How to get Max date and sum of its rows SQL

I have following table,
+------+-------------+----------+---------+
| id | date | amount | amount2 |
+------+-------------+----------+---------+
| | | | 500 |
| 1 | 1/1/2020 | 1000 | |
+------+-------------+----------+---------+
| | | | 100 |
| 1 | 1/3/2020 | 1558 | |
+------+-------------+----------+---------+
| | | | 200 |
| 1 | 1/3/2020 | 126 | |
+------+-------------+----------+---------+
| | | | 500 |
| 2 | 2/5/2020 | 4921 | |
+------+-------------+----------+---------+
| | | | 100 |
| 2 | 2/5/2020 | 15 | |
+------+-------------+----------+---------+
| | | | 140 |
| 2 | 1/1/2020 | 5951 | |
+------+-------------+----------+---------+
| | | | 10 |
| 2 | 1/2/2020 | 1588 | |
+------+-------------+----------+---------+
| | | | 56 |
| 2 | 1/3/2020 | 1568 | |
+------+-------------+----------+---------+
| | | | 45 |
| 2 | 1/4/2020 | 12558 | |
+------+-------------+----------+---------+
I need to get each Id's max date and its amount and amount2 summations, how can I do this. according to above data, I need following output.
+------+-------------+----------+---------+
| | | | 300 |
| 1 | 1/3/2020 | 1684 | |
+------+-------------+----------+---------+
| | | | 600 |
| 2 | 2/5/2020 | 4936 | |
+------+-------------+----------+---------+
How can I do this.
Aggregate and use MAX OVER to get the IDs' maximum dates:
select id, [date], sum_amount, sum_amount2
from
(
select
id, [date], sum(amount) as sum_amount, sum(amount2) as sum_amount2,
max([date]) over (partition by id) as max_date_for_id
from mytable group by id, [date]
) aggregated
where [date] = max_date_for_id
order by id;
first is to use dense_rank() to find the row with latest date
dense_rank () over (partition by id order by [date] desc)
after that, just simply group by with sum() on the amount
select id, [date], sum(amount), sum(amount2)
from
(
select *,
dr = dense_rank () over (partition by id order by [date] desc)
from your_table
) t
where dr = 1
group by id, [date]

How to insert or update a column using SQL based on sorted number of items for each item group

I have two tables 'Product' and 'product_Desc'
+-----------+-------------+
| ProductID | ProductName |
+-----------+-------------+
| 1 | A |
| 2 | B |
+-----------+-------------+
+----+-----------+-------------+-----------+
| Id | ProductID | ProductDec | SortOrder |
+----+-----------+-------------+-----------+
| 1 | 1 | Aero-pink | |
| 2 | 1 | Aero-white | |
| 3 | 1 | Aero-green | |
| 4 | 1 | Aero-Orange | |
| 5 | 2 | Baloon-1 | |
| 6 | 2 | Baloon-2 | |
| 7 | 2 | Baloon-3 | |
+----+-----------+-------------+-----------+
Now, what is the Sql code that can update 'sortOrder' column sequentially for each group of ProductID as shown below:
+----+-----------+-------------+-----------+
| Id | ProductID | ProductDec | SortOrder |
+----+-----------+-------------+-----------+
| 1 | 1 | Aero-pink | 1 |
| 2 | 1 | Aero-white | 2 |
| 3 | 1 | Aero-green | 3 |
| 4 | 1 | Aero-Orange | 4 |
| 5 | 2 | Baloon-1 | 1 |
| 6 | 2 | Baloon-2 | 2 |
| 7 | 2 | Baloon-3 | 3 |
+----+-----------+-------------+-----------+
Please note that these are sample tables, actual tables have thousands of records.
Would appreciate your help on this. Thank you
with cte
as
(
select SortOrder, row_number() over(partition by ProductID order by Id) as newPerProductOrder
from product_Desc
)
update cte
set SortOrder = newPerProductOrder
where (SortOrder <> newPerProductOrder or SortOrder is null)

SQL query for the store with the minimum price of an item in the city

I have this table
(city,storeID,itemID,price)
I need to return for each city,itemID the storeID with the minimum price for the item and the minimum price itself ( city,itemID,storeIDmin,minprice).
Can someone help me with this query ?
Thanks!
I solved this with Join and Subquery (Also possible to use "WITH AS" Clause if you work on oracle DB):
SELECT table1.city, table1.itemID, table1.storeID as storeIDmin, subquery.min_price
FROM table1
JOIN (select city, itemID, min(price) as min_price from table1
group by city,itemID) AS subquery
ON table1.city = subquery.city
AND table1.itemID = subqueryitemID
AND table1.price =
subquery.min_price
the result for example:
+------+---------+--------+-------+
| city | storeID | itemID | price |
+------+---------+--------+-------+
| 1 | 1 | 1 | 70 |
| 1 | 2 | 1 | 60 |
| 2 | 1 | 1 | 100 |
| 2 | 1 | 2 | 90 |
| 2 | 2 | 1 | 88 |
| 3 | 1 | 1 | 70 |
+------+---------+--------+-------+
will result:
+------+--------+----------+-------+
| city | itemID | storeMin | price |
+------+--------+----------+-------+
| 2 | 1 | 1 | 88 |
| 3 | 1 | 1 | 70 |
| 2 | 2 | 1 | 90 |
| 1 | 1 | 2 | 60 |
+------+--------+----------+-------+
You can approach this with a correlated subquery:
select t.*
from t
where t.price = (select min(t2.price) from t t2 where t2.itemId = t.itemId);

Convert a complex relational SQL query so that it runs in OrientDB

I am a newbie to OrientDB. I have a table structure as shown below. I have tried out a lot of queries but still cannot figure out how to implement the following SQL query in OrientDB. I need to join data from 4 different classes. Any help is greatly appreciated.
select Users.Name as uName,
Shops.Name as shopName,
ShopTotalPurchases.Total
from Users, Shops, Purchases,ShopTotalPurchases
where Users.Id=10
and Purchases.UserId=Users.Id
and Purchases.Date="date2"
and ShopTotalPurchases.Date="date2"
and ShopTotalPurchases.ShopId = Shops.Id
> reldb> SELECT * FROM Users;
+----+--------+-------+
| Id | Name | Phone |
+----+----------------+
| 10 | User 1 | 1111 |
+----+----------------+
| 20 | User 2 | 2222 |
+----+----------------+
> reldb> SELECT * FROM Shops;
+----+--------+-------+
| Id | Name | Phone |
+----+----------------+
| 30 | Shop 1 | 1111 |
+----+----------------+
| 40 | Shop 2 | 2222 |
+----+----------------+
> reldb> SELECT * FROM Purchases; [unique per combo of UserId, ShopId and Date]
+----+--------+--------+--------+------+-----------+
| Id | UserId | Item | ShopId | Date | ItemPrice |
+----+--------+-----------------+------+-----------+
| 0 | 10 | First | 30 |date1 | 100 |
+----+--------+--------+--------+------+-----------+
| 1 | 10 | Second | 30 |date2 | 200 |
+----+--------+--------+--------+------+-----------+
| 21 | 10 | Third | 40 |date3 | 300 |
+----+--------+--------+--------+------+-----------+
| 41 | 20 | Fourth | 40 |date4 | 400 |
+----+--------+--------+--------+------+-----------+
| 82 | 20 | Fift | 30 |date5 | 500 |
+----+--------+--------+--------+------+-----------+
> reldb> SELECT * FROM ShopTotalPurchases;
+----+--------+--------+------+
| Id | Total | ShopId | Date |
+----+--------+--------+------+
| 0 | 1000 | 30 |date1 |
+----+--------+--------+------+
| 1 | 2000 | 30 |date2 |
+----+--------+--------+------+
| 21 | 3000 | 40 |date2 |
+----+--------+--------+------+
you can use this query:
select $a.Name as uName, $b.Name as shopName, $c.Total as Total from Purchases
let $a = (select Name from User where Id = 10 and Id in $parent.current.UserId),
$b = (select Name from Shops where Id in $parent.current.ShopId),
$c = (select Total from ShopTotalPurchases where Date = 'date2' and ShopId in $parent.current.ShopId)
where Date = 'date2' unwind uName, shopName, Total
Console output:
----+------+-----+--------+------
# |#CLASS|uName|shopName|Total
----+------+-----+--------+------
0 |null |User1|Shop1 |2000.0
----+------+-----+--------+------

How do you join records one to one with multiple possible matches ...?

I have a table of transactions like the following
| ID | Trans Type | Date | Qty | Total | Item Number | Work Order |
-------------------------------------------------------------------------
| 1 | Issue | 11/27/2012 | 3 | 3.50 | NULL | 10 |
| 2 | Issue | 11/27/2012 | 3 | 3.50 | NULL | 11 |
| 3 | Issue | 11/25/2012 | 1 | 1.25 | NULL | 12 |
| 4 | ID Issue | 11/27/2012 | -3 | -3.50 | 100 | NULL |
| 5 | ID Issue | 11/27/2012 | -3 | -3.50 | 102 | NULL |
| 6 | ID Issue | 11/25/2012 | -1 | -1.25 | 104 | NULL |
These transactions are duplicates where the 'Issue's have a work order ID while the 'ID Issue' transactions have the item number. I would like to update the [Item Number] field for the 'Issue' transactions to include the Item Number. When I do a join on the Date, Qty, and Total I get something like this
| ID | Trans Type | Date | Qty | Total | Item Number | Work Order |
-------------------------------------------------------------------------
| 1 | Issue | 11/27/2012 | 3 | 3.50 | 100 | 10 |
| 1 | Issue | 11/27/2012 | 3 | 3.50 | 102 | 10 |
| 2 | Issue | 11/27/2012 | 3 | 3.50 | 100 | 11 |
| 2 | Issue | 11/27/2012 | 3 | 3.50 | 102 | 11 |
| 3 | Issue | 11/25/2012 | 1 | 1.25 | 104 | 12 |
The duplicates are multiplied! I would like this
| ID | Trans Type | Date | Qty | Total | Item Number | Work Order |
-------------------------------------------------------------------------
| 1 | Issue | 11/27/2012 | 3 | 3.50 | 100 | 10 |
| 2 | Issue | 11/27/2012 | 3 | 3.50 | 102 | 11 |
| 3 | Issue | 11/25/2012 | 1 | 1.25 | 104 | 12 |
Or this (Item Number is switched for the two matches)
| ID | Trans Type | Date | Qty | Total | Item Number | Work Order |
-------------------------------------------------------------------------
| 1 | Issue | 11/27/2012 | 3 | 3.50 | 102 | 10 |
| 2 | Issue | 11/27/2012 | 3 | 3.50 | 100 | 11 |
| 3 | Issue | 11/25/2012 | 1 | 1.25 | 104 | 12 |
Either would be fine. What would be a simple solution?
Use SELECT DISTINCT to filter same results out or you could partition your results to get the first item in each grouping.
UPDATE
Here's the code to illustrate the partition approach.
SELECT ID, [Trans Type], [Date], [Qty], [Total], [Item Number], [Work Order]
FROM
(
SELECT
ID, [Trans Type], [Date], [Qty], [Total], [Item Number], [Work Order], ROW_NUMBER() OVER
(PARTITION BY ID, [Trans Type], [Date], [Qty], [Total]
ORDER BY [Item Number]) AS ItemRank
FROM YourTable
) AS SubQuery
WHERE ItemRank = 1