Get Last Row of Different id then display data that is greater than zero - sql

This is my table...
+----+--------+
| id | amount |
+----+--------+
| 1 | 100 |
| 1 | 50 |
| 1 | 0 |
| 2 | 500 |
| 2 | 100 |
| 3 | 300 |
| 3 | -2 |
| 4 | 400 |
| 4 | 200 |
+----+--------+
I would like to choose from it each value of id that does not have a nonpositive (i.e. negative or 0) value associated with it, and the smallest amount associated with that id.
If I use this code...
SELECT DISTINCT id, amount
FROM table t
WHERE amount = (SELECT MIN(amount) FROM table WHERE id= t.id)
... then these results show...
+----+--------+
| id | amount |
+----+--------+
| 1 | 0 |
| 2 | 100 |
| 3 | -2 |
| 4 | 200 |
+----+--------+
But what I want the statement to return is...
+----+--------+
| id | amount |
+----+--------+
| 2 | 100 |
| 4 | 200 |
+----+--------+

Just add amount>0 in your query. You missed out that condition in your query. That should do it.
SELECT DISTINCT id, amount FROM table t
WHERE amount = (SELECT MIN(amount) FROM table WHERE id= t.id)
and amount>0;

If you want to display id, where min(amount) > 0, the use this.
SELECT id, min(amount) as amount
FROM table t
group by id
having min(amount) > 0;

Please try the following...
SELECT id,
MIN( amount )
FROM table
WHERE amount > 0
GROUP BY id
ORDER BY id;
This statement starts by selecting all records WHERE amount is larger than 0.
The records from the resulting dataset are then grouped by each surviving value of id and the smallest value of amount is chosen for that GROUP / id.
The resulting pairs of values are then sorted by ORDER id and returned to the user.
If you have any questions or comments, then please feel free to post a Comment accordingly.

Related

How to join two tables with sum of one column and with condition

I have two tables:
table 1
+-------------+--------------+-----------------+
| id_product | id_customer |start_date |
+-------------+--------------+-----------------+
| 1 | 1 | 2021-08-28T10:37|
| 1 | 2 | 2021-08-28T11:17|
| 1 | 3 | 2021-08-28T12:27|
| 2 | 1 | 2021-08-28T17:00|
table 2
+-------------+------------------+----------+-------------------------------+
| id_customer | stop_date | duration | 20 other columns like duration|
+-------------+------------------+----------+-------------------------------+
| 1 | 2021-08-27T17:00| 20 | ...
| 1 | 2021-08-26T17:00| 40 | ...
| 2 | 2021-08-29T17:00| 120 | ...
| 1 | 2021-08-30T17:00| 40 | ...
| ..........................................|
start_date in table 1 is the date the customer started the product.
stop_datein table 2 is the date the customer stopped the product.
I want to join these two tables to have something like : one row with :
productid
customer_id
start_date
sum of all duration for all the stop_date BEFORE start_date.
same as duration for all the 20 reminding columns.
example for product_id = 1, custom_id = 1 :
+-------------+--------------+-----------------+---------------+-----------------------------------+
| id_product | id_customer |start_date | sum(duration) | sum(all other columns from table 2)
+-------------+--------------+-----------------+---------------+-----------------------------------+
| 1 | 1 | 2021-08-28T10:37| 60
I have a really big tables, I am using pyspark with SQL. Do you know an optimised way to this ?
Thank you
EDIT :
There is also an id_product in table2
SELECT
Table_1.id_product,
Table_1.id_customer,
Table_1.start_date,
SUM(duration) AS [sum(duration)]
---,SUM(duration2)
---,SUM(duration3)
FROM Table_1
LEFT JOIN Table_2 ON
Table_2.id_customer = Table_1.id_customer
AND Table_2.id_product = Table_1.id_product
AND Table_2.stop_date < Table_1.start_date
GROUP BY Table_1.id_product,Table_1.id_customer, Table_1.start_date

sum last values and group by

I have "steps" table like this
id | points | game_id | price | user_id | timestamp | some | additional | fields
it contains game information.
I have a code which can group by game_id
SELECT game_id, MIN(timestamp),
(SELECT points FROM steps as t2 WHERE t2.game_id = t1.game_id ORDER BY t2.id DESC LIMIT 1) as last_point
WHERE user_id = 1
GROUP BY game_id
but I want to group by price and summarize each last point of the game. my query is
SELECT COUNT(DISTINCT game_id) as game_count, COUNT(id) as step_count, SUM(points), price
FROM steps WHERE user_id = 1
GROUP BY price
But this query returns a sum of all points while I need a sum of the last point in each game.
Please point me to the right way
Example result
last_points_sum | game_count | step_count | price
200 | 2 | 3 | 100
400 | 3 | 4 | 200
where table is
id | points | game_id | price | user_id | timestamp
1 | 10 | 5 | 100 | 1 | 100000001
2 | 200 | 5 | 100 | 1 | 100000002
3 | 200 | 6 | 200 | 1 | 100000003
4 | 0 | 6 | 200 | 1 | 100000004
5 | 400 | 6 | 200 | 1 | 100000005
Is this what you're looking for?
This assumes that timestamp is unique, at least for each instance of game_id.
SELECT
COUNT(DISTINCT game_id) AS game_count,
COUNT(id) AS step_count,
SUM(COALESCE(ltIsLastPoints, 0.0) * points),
price
FROM
(SELECT
game_id ltGameID,
MAX(timestamp) ltTimestamp,
1.0 ltIsLastPoints
FROM
steps
GROUP BY
game_id
) lt RIGHT JOIN
steps
ON ltGameID = game_id
AND ltTimestamp = timestamp
WHERE
user_id = 1
GROUP BY
price;
Your description says you want to group by points but your example query groups by price. I went with price.

Loop over one table, subselect another table and update values of first table with SQL/VBA

I have a source table that has a few different prices for each product (depending on the order quantity). Those prices are listed vertically, so each product could have more than one row to display its prices.
Example:
ID | Quantity | Price
--------------------------
001 | 5 | 100
001 | 15 | 90
001 | 50 | 80
002 | 10 | 20
002 | 20 | 15
002 | 30 | 10
002 | 40 | 5
The other table I have is the result table in which there is only one row for each product, but there are five columns that each could contain the quantity and price for each row of the source table.
Example:
ID | Quantity_1 | Price_1 | Quantity_2 | Price_2 | Quantity_3 | Price_3 | Quantity_4 | Price_4 | Quantity_5 | Price_5
---------------------------------------------------------------------------------------------------------------------------
001 | | | | | | | | | |
002 | | | | | | | | | |
Result:
ID | Quantity_1 | Price_1 | Quantity_2 | Price_2 | Quantity_3 | Price_3 | Quantity_4 | Price_4 | Quantity_5 | Price_5
---------------------------------------------------------------------------------------------------------------------------
001 | 5 | 100 | 15 | 90 | 50 | 80 | | | |
002 | 10 | 20 | 20 | 15 | 30 | 10 | 40 | 5 | |
Here is my Python/SQL solution for this (I'm fully aware that this could not work in any way, but this was the only way for me to show you my interpretation of a solution to this problem):
For Each result_ID In result_table.ID:
Subselect = (SELECT * FROM source_table WHERE source_table.ID = result_ID ORDER BY source_table.Quantity) # the Subselect should only contain rows where the IDs are the same
For n in Range(0, len(Subselect)): # n (index) should start from 0 to last row - 1
price_column_name = 'Price_' & (n + 1)
quantity_column_name = 'Quantity_' & (n + 1)
(UPDATE result_table
SET result_table.price_column_name = Subselect[n].Price, # this should be the price of the n-th row in Subselect
result_table.quantity_column_name = Subselect[n].Quantity # this should be the quantity of the n-th row in Subselect
WHERE result_table.ID = Subselect[n].ID)
I honestly have no idea how to do this with only SQL or VBA (those are the only languages I'd be able to use -> MS-Access).
This is a pain in MS Access. If you can enumerate the values, you can pivot them.
If we assume that price is unique (or quantity or both), then you can generate such a column:
select id,
max(iif(seqnum = 1, quantity, null)) as quantity_1,
max(iif(seqnum = 1, price, null)) as price_1,
. . .
from (select st.*,
(select count(*)
from source_table st2
where st2.id = st.id and st2.price >= st.price
) as seqnum
from source_table st
) st
group by id;
I should note that another solution would use data frames in Python. If you want to take that route, ask another question and tag it with the appropriate Python tags. This question is clearly a SQL question.

calculating sum of rows with identical id

Let's imagine a table with two columns ex:
| Value | ID |
+-------+----+
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 1 | 2 |
| 2 | 2 |
| 2 | 2 |
What I am trying to do is to calculate the sum of those with similar id and display them in different table like:
| Sum | ID |
+-----+----+
| 9 | 1 |
| 5 | 2 |
and so on.
I could find a sum of a known id by
SELECT SUM(VALUE) FROM MYTABLE WHERE ID = 1;
However not sure on how to find sum of different id's separately, could you give an idea on how to proceed?
Select SUM(VALUE),ID FROM MYTABLE GROUP BY ID
Use GROUP BY clause:
SELECT SUM(VALUE) Sum, ID FROM MYTABLE GROUP BY ID;
SELECT SUM(VALUE),ID FROM MYTABLE Group By ID

Order rows based on different column value

I have data in table in following format.
CustomerID | CustomerName | DisplayOrder | isActive
1 | Test | 1 | 1
1 | Test | 2 | 1
2 | Test2 | 1 | 1
1 | Test | 3 | 1
2 | Test2 | 2 | 1
Above table need to be sorted based on displayorder column per customer. Each customer will have thier own display order. Here I cannot use OrderBy Clause direcly because Display order will repear per customer.
Expected Output is:
CustomerID | CustomerName | DisplayOrder | isActive
1 | Test | 1 | 1
1 | Test | 2 | 1
1 | Test | 3 | 1
2 | Test2 | 1 | 1
2 | Test2 | 2 | 1
Please help on order by clause to sort based on customer.
You just need to sort by customerId and then display order (if customer id is same) like:
SELECT *
FROM mytable
ORDER BY customerId, displayOrder;
Fiddle for the same.
SELECT *
FROM t
ORDER BY CustomerID,
DisplayOrder;