Each row 3 column sum result show as running total in last column, then from 2nd row > first row running total show in first column with group by - oracle

Each row Total value go for the set OP value for the next row, except the first row
My Table Data
Id
WarehouseId
ProductId
OP
RE
IS
Total
1
100
10000
10
0
0
10
2
100
10000
0
0
5
5
4
100
10000
0
15
0
15
5
101
10001
15
0
0
15
6
101
10001
0
0
5
5
8
101
10001
0
15
0
15
9
101
10002
25
0
0
25
10
101
10002
0
0
10
10
11
101
10002
0
15
0
15
I want to show below result (OP+RE)-IS=Total
Id
WarehouseId
ProductId
OP
RE
IS
Total
1
100
10000
10
0
0
10
2
100
10000
10
0
5
5
4
100
10000
5
15
0
20
5
101
10001
15
0
0
15
6
101
10001
15
0
5
10
8
101
10001
10
15
0
25
9
101
10002
25
0
0
25
10
101
10002
25
0
10
15
11
101
10002
15
15
0
30

You can use recursive subquery factoring for that purpose like below. You need to rank your data as you have some gaps between IDs in your data. Column name = IS is not allowed, You should use "IS" enclosed by ".
with t1 ( ID, WAREHOUSEID, PRODUCTID, OP, RE, "IS", RNB, rnb_per_wh_prod) as (
select ID, WAREHOUSEID, PRODUCTID, OP, RE, "IS"
, row_number()over(order by WAREHOUSEID, PRODUCTID, ID) rnb
, row_number()over(partition by WAREHOUSEID, PRODUCTID order by ID) rnb_per_wh_prod
from Your_table t
), cte (ID, WAREHOUSEID, PRODUCTID, OP, RE, "IS", Total, RNB) as (
select ID, WAREHOUSEID, PRODUCTID, OP, RE, "IS", OP + RE - "IS", RNB
from t1
where rnb_per_wh_prod = 1
union all
select t1.ID
, t1.WAREHOUSEID
, t1.PRODUCTID
, case when t1.op = 0 then c.OP + c.RE - c."IS" else t1.OP end as OP
, t1.RE
, t1."IS"
, case when t1.op = 0 then c.OP + c.RE - c."IS" else t1.OP end + t1.RE - t1."IS" total
, t1.RNB
from cte c
join t1 on (t1.RNB = c.RNB + 1
and c.WAREHOUSEID = t1.WAREHOUSEID
and c.PRODUCTID = t1.PRODUCTID)
)
select ID, WAREHOUSEID, PRODUCTID, OP, RE, "IS", TOTAL
from cte
order by id
;

If I understand the problem correctly, "every 3 row" is a coincidence in your data; in fact, the computation must be done separately for each product in each warehouse, no matter how many rows there are for each distinct combination. And the "id" column is in reality some sort of timestamp - ordering is by "id".
If so, you can do it all in a single query using analytic sum(). Instead of creating a table for testing, I included all the sample data in a WITH clause at the top of the query itself; you can remove the WITH clause, and use your actual table and column names. I also changed the column name is to is_ since is is a reserved keyword, it can't be a column name.
Note also that I am ignoring your existing total column completely (I didn't even include it in the sample data); I assume it doesn't exist in your real-life data, and instead it is part of your attempt at a solution. You don't need it - not in the way you have it in your question.
with
sample_data (id, warehouseid, productid, op, re, is_) as (
select 1, 100, 10000, 10, 0, 0 from dual union all
select 2, 100, 10000, 0, 0, 5 from dual union all
select 4, 100, 10000, 0, 15, 0 from dual union all
select 5, 101, 10001, 15, 0, 0 from dual union all
select 6, 101, 10001, 0, 0, 5 from dual union all
select 8, 101, 10001, 0, 15, 0 from dual union all
select 9, 101, 10002, 25, 0, 0 from dual union all
select 10, 101, 10002, 0, 0, 10 from dual union all
select 11, 101, 10002, 0, 15, 0 from dual
)
select id, warehouseid, productid,
nvl(sum(op + re - is_) over (partition by warehouseid, productid
order by id rows between unbounded preceding and 1 preceding),
op) as op,
re, is_,
sum(op + re - is_) over
(partition by warehouseid, productid order by id) as total
from sample_data
;
ID WAREHOUSEID PRODUCTID OP RE IS_ TOTAL
------ ----------- ---------- ---------- ---------- ---------- ----------
1 100 10000 10 0 0 10
2 100 10000 10 0 5 5
4 100 10000 5 15 0 20
5 101 10001 15 0 0 15
6 101 10001 15 0 5 10
8 101 10001 10 15 0 25
9 101 10002 25 0 0 25
10 101 10002 25 0 10 15
11 101 10002 15 15 0 30

Related

How to count or sum distinct values when there is a risk of intersection?

Imagine I have a table with people and their features:
group Name red_hair tall blue_eyes programmer
1 Mark 1 1 0 1
1 Sean 1 0 1 0
1 Lucas 1 1 1 1
2 Linda 0 1 1 1
I would like to count how many people of specific sets of features are in every group. In other words, I would like to make some bins without counting a person multiple times.
There are 2^4 (16) possible combinations of those sets, but I don't need so much.
For example, if a person has red_hair I don't care whether he or she has blue eyes or he or she a programmer. This person goes to the red hair bin of this group.
If a person is a programmer I don't care whether he or she is tall, but I don't want to count people who are already in a red hair bin. Because I have already counted them.
So I have a priority:
Red hair people counts first
Programmers second
People with blue eyes third
Expected result of this dataset:
group red_hair_persons programmers blue_eyes_persons
1 3 0 0
2 0 1 0
when I do this:
select group, count(case when red_hair = 1 then name end) as red_hair,
count(case when programmer = 1 and red_hair = 0 then name end) as programmers
from table
group by group
I fear that there would be some intersections. Or the logic with CASES would be so complex I could drown in it.
Am I right?
If so how could I avoid them? Maybe I am doing everything wrong and there is a better way to do what I want to. I have an enormous table with many features in it and I don't want to screw up.
Here's how I understood it:
SQL> with test (cgroup, name, red_hair, tall, blue_eyes, programmer) as
2 (select 1, 'mark' , 1, 1, 0, 1 from dual union all
3 select 1, 'sean' , 1, 0, 1, 0 from dual union all
4 select 1, 'lucas', 1, 1, 1, 1 from dual union all
5 select 2, 'linda', 0, 1, 1, 1 from dual
6 ),
7 priority as
8 (select t.*,
9 case when red_hair = 1 then 'A'
10 when programmer = 1 then 'B'
11 when blue_eyes = 1 then 'C'
12 else 'D'
13 end priority
14 from test t
15 )
16 select cgroup,
17 sum(case when priority = 'A' then 1 else 0 end) red_hair,
18 sum(case when priority = 'B' then 1 else 0 end) programmer,
19 sum(case when priority = 'C' then 1 else 0 end) blue_eyes,
20 sum(case when priority = 'D' then 1 else 0 end) other
21 from priority
22 group by cgroup;
CGROUP RED_HAIR PROGRAMMER BLUE_EYES OTHER
---------- ---------- ---------- ---------- ----------
1 3 0 0 0
2 0 1 0 0
SQL>
priority CTE puts every person into its priority group, based on their properties
the final select counts (using SUM + CASE) them per group
With a little bit of simple math involved in the conditional aggregation:
select "group",
sum("red_hair") red_hair_persons,
sum((1 - "red_hair") * "programmer") programmers,
sum((1 - "red_hair") * (1 - "programmer") * "blue_eyes") blue_eyes_persons
from tablename
group by "group"
See the demo.
Results:
> group | RED_HAIR_PERSONS | PROGRAMMERS | BLUE_EYES_PERSONS
> ----: | ---------------: | ----------: | ----------------:
> 1 | 3 | 0 | 0
> 2 | 0 | 1 | 0

Need output in below format in oracle. I have tried with lag function it worked if we have only 2 rows in table

Consider below table table.
Id balance
1 100
2 500
3 4000
I need output in below format.
Id balance begin_bal end_bal
1 100 0 100
2 500 100 600
3 4000 600 4600
A little bit of analytics, as you presumed:
SQL> with test (id, balance) as
2 (select 1, 100 from dual union all
3 select 2, 500 from dual union all
4 select 3, 4000 from dual
5 ),
6 temp as
7 (select id, balance, sum(balance) over (order by id) rsum
8 from test
9 )
10 select id,
11 balance,
12 nvl(lag(rsum) over (order by id), 0) begin_bal,
13 rsum end_bal
14 from temp
15 order by id;
ID BALANCE BEGIN_BAL END_BAL
---------- ---------- ---------- ----------
1 100 0 100
2 500 100 600
3 4000 600 4600
SQL>

Sum all columns in a row

How can I get a total results of all my rows? (for ORACLE)
SELECT
NAME,
SUM(CASE WHEN ASSIST_1 = 'YES' THEN 1 END) WEEK1,
SUM(CASE WHEN ASSIST_2 = 'YES' THEN 1 END) WEEK2,
SUM(CASE WHEN ASSIST_3 = 'YES' THEN 1 END) WEEK3,
FROM TABLE_NAME
WHERE GROUP BY NAME;
I have this results:
Name week1 week2 week3
Anne 1 2 3
Bob 3 1 0
Charlie 4 5 1
I want this result:
Anne 1 2 3
Bob 3 1 0
Charlie 4 5 1
Total 8 8 4
How can I get a total results of all my rows?
By using rollup() extension of the group by clause. Something like this(just an example):
-- sample of date from your question
with t1(uname, c1, c2, c3) as(
select 'Anne' , 1, 2, 3 from dual union all
select 'Bob' , 3, 1, 0 from dual union all
select 'Charlie', 4, 5, 1 from dual
)
-- actual query
select case grouping(uname)
when 0 then uname
else 'Total' end
as uname1
, sum(c1) as c1
, sum(c2) as c2
, sum(c3) as c3
from t1
group by rollup(uname)
order by grouping(uname)
Result:
UNAME1 C1 C2 C3
------- ---------- ---------- ----------
Anne 1 2 3
Bob 3 1 0
Charlie 4 5 1
Total 8 8 4
4 rows selected.
Use UNION ALL with SUM values
WITH t1(name, week1, week2, week3) AS
( SELECT 'Anne', 1, 2, 3 FROM dual
UNION ALL
SELECT 'Bob', 3, 1, 0 FROM dual
UNION ALL
SELECT 'Charlie', 4, 5, 1 FROM dual
),
s AS
(SELECT 'Total' name,
SUM(week1) week1,
SUM(week2) week2,
SUM(week2) week3
FROM t1
)
SELECT * FROM t1
UNION ALL
SELECT * FROM s;
Result:
NAME WEEK1 WEEK2 WEEK3
Anne 1 2 3
Bob 3 1 0
Charlie 4 5 1
Total 8 8 8
Base on #Nicholas answer:
SELECT
CASE GROUPING(NAME) WHEN 0 THEN NAME ELSE 'TOTAL' END AS NAME,
SUM (WEEK1) AS WEEK1,
SUM (WEEK2) AS WEEK2,
SUM (WEEK3) AS WEEK3
FROM (
SELECT
NAME,
SUM(CASE WHEN ASSIST_1 = 'YES' THEN 1 END) WEEK1,
SUM(CASE WHEN ASSIST_2 = 'YES' THEN 1 END) WEEK2,
SUM(CASE WHEN ASSIST_3 = 'YES' THEN 1 END) WEEK3,
FROM TABLE_NAME
WHERE GROUP BY (NAME)
GROUP BY ROLLUP(NAME)
ORDER BY GROUPING(NAME);
Give this result:
Anne 1 2 3
Bob 3 1 0
Charlie 4 5 1
Total 8 8 4

add a new column for unique ID in hive table

i have a table in hive with two columns: session_id and duration_time like this:
|| session_id || duration||
1 14
1 10
1 20
1 10
1 12
1 16
1 8
2 9
2 6
2 30
2 22
i want to add a new column with unique id when:
the session_id is changing or the duration_time > 15
i want the output to be like this:
session_id duration unique_id
1 14 1
1 10 1
1 20 2
1 10 2
1 12 2
1 16 3
1 8 3
2 9 4
2 6 4
2 30 5
2 22 6
any ideas how to do that in hive QL?
thanks!
SQL tables represent unordered sets. You need a column specifying the ordering of the values, because you seem to care about the ordering. This could be an id column or a created-at column, for instance.
You can do this using a cumulative sum:
select t.*,
sum(case when duration > 15 or seqnum = 1 then 1 else 0 end) over
(order by ??) as unique_id
from (select t.*,
row_number() over (partition by session_id order by ??) as seqnum
from t
) t;

How to sort individual rows in descending order?

I have a table which looks like the following:
Name LastName tPoints aPoints sPoints gPoints type
John Johnny 15 14 13 10 1
Joe P. 12 11 26 10 1
Matt Q. 11 26 37 44 2
Sorine P. 55 9 8 7 2
Ali Ahmed 30 44 88 65 2
... ... .. .. .. .. 3
3
I would like to sort INDIVIDUAL ROWS and display based on TYPE
NOTE: i can't use order by in oracle because it sorts only 1 row and the others
is sorted based on the first row
I don't want to break the table apart into individual tables, then sort it, and then update it back to the original table.
so, the output will looks something like this, for tPoints - i need to display all
15 - John Johnny
12 - Joe P.
and for aPoints
44 - Ali Ahmed
26 - Matt Q.
9 - Sorine P.
and so on ...
in a nutshell, if type = 1 then sort tPoints in descending, if type = 2 then sort aPoints, if type = 3 then sort sPoints, and so on....
what would be an efficient way to chive this?
Regards,
For the sake of simplicity this example includes only two types. Add as many types as you need.
SQL> with t1(Name1, LastName, tPoints, aPoints, sPoints, gPoints, type1) as(
2 select 'John' , 'Johnny', 15, 14, 13, 10, 1 from dual union all
3 select 'Joe' , 'P.' , 12, 11, 26, 10, 1 from dual union all
4 select 'Matt' , 'Q.' , 11, 26, 37, 44, 2 from dual union all
5 select 'Sorine', 'P.' , 55, 9 , 8 , 7, 2 from dual union all
6 select 'Ali' , 'Ahmed' , 30, 44, 88, 65, 2 from dual
7 )
8 select type1
9 , tpoints
10 , apoints
11 , name1
12 , Lastname
13 from t1
14 order by case when type1=1 then tpoints else type1 end desc,
15 case when type1=2 then apoints else type1 end desc;
TYPE1 TPOINTS APOINTS NAME1 LASTNAME
---------- ---------- ---------- ------ --------
1 15 14 John Johnny
1 12 11 Joe P.
2 30 44 Ali Ahmed
2 11 26 Matt Q.
2 55 9 Sorine P.

Resources