Simple query in DB2 for AS400 - sql

This is a very easy query (I think) but I stil can't do it.
I have some data like this:
A B C
1 1100 5
1 1100 5
1 500 1
2 1200 4
2 1200 4
2 600 1
3 1300 3
3 1300 3
3 700 1
And I want to return the top B per A with the SUM of C, or something like this:
A B C
1 1100 10
2 1200 8
3 1300 6
Also, I'm using DB2 for AS400, so I can't use the TOP keyword.
EDIT # OMG Ponies:
I tried somethine like
SELECT
t.A
,MAX(t.B)
,SUM(t.C)
FROM t
GROUP BY
t.A
But it returns the total sum of C, not only the ones selected:
A B C
1 1100 11
2 1200 9
3 1300 7
Thanks!

Looks like you want the max B value for each A value, so
SELECT t.a,
MAX(t.b)
FROM TABLE t
GROUP BY t.a
If you want entire record associated with the A and MAX(b) values, use:
SELECT t.a,
t.b,
t.c
FROM TABLE t
JOIN (SELECT x.a,
MAX(x.b) AS max_b
FROM TABLE x
GROUP BY x.a) y ON y.a = t.a
AND y.max_b = t.b

On DB2 you can use the FETCH FIRST # ROWS ONLY
to mimic the TOP predicate but it goes at the END of the SQL statement

Related

Counting SUM(VALUE) from previous cell

I have the following table:
A
Sum(Tickets)
01-2022
5
02-2022
2
03-2022
8
04-2022
1
05-2022
3
06-2022
3
07-2022
4
08-2022
1
09-2022
5
10-2022
5
11-2022
3
I would like to create the following extra column 'TotalSum(Tickets)' but I am stuck....
Anyone who can help out?
A
Sum(Tickets)
TotalSum(Tickets)
01-2022
5
5
02-2022
2
7
03-2022
8
15
04-2022
1
16
05-2022
3
19
06-2022
3
22
07-2022
4
26
08-2022
1
27
09-2022
5
32
10-2022
5
37
11-2022
3
40
You may use SUM() as a window function here:
SELECT A, SumTickets, SUM(SumTickets) OVER (ORDER BY A) AS TotalSumTickets
FROM yourTable
ORDER BY A;
But this assumes that you actually have a bona-fide column SumTickets which contains the sums. Assuming you really showed us the intermediate result of some aggregation query, you should use:
SELECT A, SUM(Tickets) AS SumTickets,
SUM(SUM(Tickets)) OVER (ORDER BY A) AS TotalSumTickets
FROM yourTable
GROUP BY A
ORDER BY A;
left join the same table where date is not bigger, then sum that for every date:
select
table1.date,
sum(t.tickets)
from
table1
left join table1 t
on t.date<= table1.date
group by
table1.date;

postgreSQL - fill in blank date rows per ID

I have a table which looks like this:
ID
money_earned
days_since_start
1
1000
1
1
2000
2
1
3000
4
1
2000
5
2
1000
1
2
100
3
I want that rows, without a days_since_start (which means that the money_earned column was empty that day) - will include all the days PER ID, and fill the money_earned with last known value, so it to look like this:
ID
money_earned
days_since_start
1
1000
1
1
2000
2
1
2000
3
1
3000
4
1
2000
5
2
1000
1
2
1000
2
2
100
3
I have tried to look up for something like that, but I don't even know what function does that...
thank you!
You can try to use CTE RECURSIVE with OUTER JOIN and LAG window function to make it.
WITH RECURSIVE CTE
AS
(
SELECT ID,MIN(days_since_start) min_num,MAX(days_since_start) max_num
FROM T
GROUP BY ID
UNION ALL
SELECT ID,min_num+1,max_num
FROM CTE
WHERE min_num+1 <= max_num
)
SELECT c.ID,
CASE WHEN t1.ID IS NULL THEN LAG(money_earned) OVER(PARTITION BY c.ID ORDER BY c.min_num) ELSE money_earned END,
c.min_num days_since_start
FROM CTE c
LEFT JOIN T t1
ON c.min_num = t1.days_since_start
AND c.ID = t1.ID
ORDER BY c.ID
sqlfiddle

sql - query for all values in table with limit

I have an SQL query which I run in Amazon Athena:
select
A,
B,
C,
D,
from
T
where
A = '1000'
order by
B desc
limit 1
where I order by B and take the first row only for the value 1000 for A. However I want to run this query for all values of A in T i.e for each A in T get the first row only and append to the results.
How do I do this?
Example of table data:
A B C D
1000 '12/01/2021' 1 7
1000 '10/01/2020' 2 8
1333 '06/01/1920' 3 9
1333 '07/01/1920' 4 10
1999 '09/03/1960' 5 11
1999 '09/03/1950' 6 12
and the result I want to get is:
1000 '12/01/2021' 1 7
1333 '07/01/1920' 4 10
1999 '09/03/1960' 5 11
You can try to use ROW_NUMBER window function to make it.
SELECT A,
B,
C,
D
FROM (
SELECT *,ROW_NUMBER() OVER(PARTITION BY A ORDER BY B DESC) rn
FROM T
) t1
WHERE rn = 1

SQL combining of a COUNT with a WHERE in single query

Here is the data, call it table T
A B
-- --
1 14
2 15
3 16
4 1
4 3
4 6
4 9
4 12
4 15
I would like to get the value of A that has only one value and a B value of 15.
There are two rows where B=15 but there are 6 rows where A=4 and only one row where A=2.
So the correct SQL should return me the 2.
I have tried this but it returns both rows.
select A from T group by A,B having Count(A) = 1 and B = 15
This similarly fails:
select A from T where B = 15 group by A having count( A ) = 1
Try this:
select A
from T
group by A
having Count(A) = 1 and Max(B) = 15;
Your problem seems to be that you are grouping by both columns. You only want to group by A.
Admittedly, your query has group by A, T, but I think that is a typo, based on the described behavior.
You can check the count of B after grouping by A.
select A
from T
group by A
having Count(B) = 1 and max(B) = 15

Looping with SQL statements

I am trying to implement a small logic in SQL:
For example : I have two tables A and B
A B
ID Qnt ID Qnt Value
1 50 1 100 1000
2 130 2 200 1000
3 180 3 300 1000
4 320 4 400 2000
5 500 5 500 2000
6 600 2000
7 700 2000
I would to loop through each value of Qnt in TABLE A and check if the value lie between the range of the values in Qnt of TABLE B and get the corresponding value.
I know how I could achieve this with using While loop. But I don't want to do this since looping affects my query performance significantly. I would like to do this with only SQL statements.
Can anyone suggest an idea how I could go with this? just an idea would be great! Any sql would be fine, I would like to know just the logic.
The output would look like :
Output
ID Qnt Value
1 50 1000
2 130 1000
3 180 1000
4 320 2000
5 500 2000
Thanks
This is a lookup. You can do it with a correlated subquery, although the syntax is a bit different in the two databases. Here is the MySQL version:
select a.*,
(select b.value
from b
where b.qnt <= a.qnt
order by b.qnt desc
limit 1
) as value
from a;
Here is the SQL Server version:
select a.*,
(select top 1 b.value
from b
where b.qnt <= a.qnt
order by b.qnt desc
) as value
from a;