Oracle - some problems with Group Operations - oracle

I need your help ... i tryed more time but can't find a soluction (i think that is simple but I have errors in oracle :( :( )
an example:
i have a table with
teams: what team played
gameDate: when played
goalHours: when teamA or teamB do a goal
goalNumber: how much goal are doing in the same hour
endGame: when finish the game
teams gameDate goalHours goalNumber endGame
team01-VS-team02 20110901 21 2 20110902
team01-VS-team02 20110901 22 1 20110902
team01-VS-team02 20110901 23 3 20110902
team03-VS-team02 20110902 18 3 20110905
team03-VS-team02 20110902 19 1 20110905
team04-VS-team02 20110904 06 5 20110906
team01-VS-team02 20110101 18 1 20110902
I need a select with all distinct teamA-VS-teamB the last gameDate
i need for every distinct teamA-VS-teamB, in their last game, the distinct hours of goalHours, the sum of goalNumber, and when stop the game.
something like this:
teams lastGameDate distinctGoalHours sumGoalNumber endGame
team01-VS-team02 20110901 3 6 20110902
team03-VS-team02 20110902 2 4 20110905
team04-VS-team02 20110904 1 5 20110906
i try with:
SELECT teams,
MAX(gameDate),
MAX (endDate),
SUM (goalNumber),
COUNT (DISTINCT goalHours)
FROM myTable
GROUP BY teams
this select doesn't work well because i don't want count
team01-VS-team02 20110101 18 1 20110902, this isn't last game date.
with this select i have 4 distinctGoalHours and 7 sumGoalNumber.
i need a select with
team01-VS-team02 20110901 3 6 20110902
team03-VS-team02 20110902 2 4 20110905
team04-VS-team02 20110904 1 5 20110906
... I hope that i show you all information that you need and thank you very much! :D

Like any other SQL, you need to restrict the result set with the appropriate filter. In your case, you need to use a sub-query to identify the latest gameDate for each team.
There are several different ways of implementing this. Here is one which works:
SQL> SELECT teams,
MAX(gameDate),
MAX (endGame),
SUM (goalNumber),
COUNT (DISTINCT goalHours)
FROM myTable
WHERE (teams, gameDate) IN
( select teams, max(gameDate)
from myTable
GROUP BY teams )
GROUP BY teams
/
2 3 4 5 6 7 8 9 10 11 12
TEAMS MAX(GAMED MAX(ENDGA SUM(GOALNUMBER) COUNT(DISTINCTGOALHOURS)
------------------------------ --------- --------- --------------- ------------------------
team03-VS-team02 02-SEP-11 05-SEP-11 4 2
team01-VS-team02 01-SEP-11 02-SEP-11 6 3
team04-VS-team02 04-SEP-11 06-SEP-11 5 1
SQL>

You need to include the gameDate in the group by. Something like:
SELECT teams
, gameDate
, MAX( endDate )
, SUM( goalNumber )
, COUNT( DISTINCT goalHours )
FROM myTable
GROUP BY teams
, gameDate

Related

Full Date Range

1st time posting here, so sorry if I messed something up.
I'm trying to figure out how many units pre day are being used across multiple products given a date range.
So if I had a table like this:
Product_id
Start_date
End_date
Units
1
07/07/2021
07/09/2021
2
2
07/08/2021
07/10/2021
4
3
07/12/2021
07/12/2021
7
The output should be something like:
Date
Units
07/07/2021
2
07/08/2021
6
07/09/2021
6
07/10/2021
4
07/11/2021
0
07/12/2021
7
Here's one option; read comments within code.
SQL> with
2 calendar as
3 -- all dates between the first START_DATE and the last END_DATE.
4 -- You need it for outer join with data you have.
5 (select mindat + level - 1 as datum
6 from (select min(start_date) mindat,
7 max(end_date) maxdat
8 from test
9 )
10 connect by level <= maxdat - mindat + 1
11 )
12 -- final query
13 select c.datum,
14 nvl(sum(t.units), 0) units
15 from calendar c left join test t on c.datum between t.start_date and t.end_date
16 group by c.datum
17 order by c.datum;
DATUM UNITS
---------- ----------
07/07/2021 2
07/08/2021 6
07/09/2021 6
07/10/2021 4
07/11/2021 0
07/12/2021 7
6 rows selected.
SQL>

PL/SQL funtion with If

I have a production records system, where the user selects the date, time, area, line, shift, and model. Introduce the number of fabric pieces in one hour in the field pieces. After adding another record, the user enters again the number of pieces, but it must also appear in another field, Total pieces, the total of pieces, that is, the sum of the current one plus the previous record.
This is the table
Date-------Time---------Area-------Line----Shift-----Model----Pieces-------Total volume
8/8/20-------7--------------A-----------1---------1--------XC1--------2--------------------2
8/8/20-------8--------------A-----------1---------1--------XC1--------3--------------------5
8/8/20-------9--------------A-----------1---------1--------XC1--------2--------------------7
The function should not add anything at the beginning of the day, and the following records should be added as long as the date, line, area, shift and model are the same.
I had planned to use a PL/SQL function where if the time is 7 (the start) it show the same number that was entered in pieces, but if it is another time (8 for example), select the pieces data in the database of the record that has the same date, area, line, shift, and model but the time is the previous one (hour-1).
I don't know if this can be done, I would appreciate your help.
I wouldn't store total_volume into a table; calculate it using sum function in its analytic form. This is, after all, Oracle Apex (I presume interactive or classic report).
Here's an example (sample data from lines #1 - 14; query that actually does the job begins at line #15):
SQL> with test (datum, time, model, pieces) as -- Expected result:
2 (select date '2020-08-08', 7 , 'XC1', 2 from dual union all -- 2
3 select date '2020-08-08', 8 , 'XC1', 3 from dual union all -- 5
4 select date '2020-08-08', 9 , 'XC1', 2 from dual union all -- 7
5 --
6 select date '2020-08-09', 7 , 'XC1', 1 from dual union all -- 1
7 select date '2020-08-09', 8 , 'XC1', 3 from dual union all -- 4
8 select date '2020-08-09', 10, 'XC1', 2 from dual union all -- 6
9 select date '2020-08-09', 11, 'XC1', 1 from dual union all -- 7
10 select date '2020-08-09', 12, 'XC1', 6 from dual union all -- 13
11 --
12 select date '2020-08-09', 9 , 'XC2', 5 from dual union all -- 5
13 select date '2020-08-09', 10, 'XC2', 4 from dual -- 9
14 )
15 select datum, time, model, pieces,
16 sum(pieces) over (partition by datum, model order by time) total_volume
17 from test
18 order by datum, model, time;
DATUM TIME MOD PIECES TOTAL_VOLUME
---------- ---------- --- ---------- ------------
08/08/2020 7 XC1 2 2
08/08/2020 8 XC1 3 5
08/08/2020 9 XC1 2 7
09/08/2020 7 XC1 1 1
09/08/2020 8 XC1 3 4
09/08/2020 10 XC1 2 6
09/08/2020 11 XC1 1 7
09/08/2020 12 XC1 6 13
09/08/2020 9 XC2 5 5
09/08/2020 10 XC2 4 9
10 rows selected.
SQL>

only keep distinct rows when doing collect_set over a moving windowing function in hive

Lets say I have a hive table that has 3 rows: merchant_id, week_id, acc_id. My goal is to collect the unique customers in the previous 4 weeks for each week and I am using a moving window to do this.
My codes:
create a test table:
CREATE TABLE table_test_test (merchant_id INT, week_id INT, acc_id INT);
INSERT INTO TABLE table_test_test VALUES
(1,0,8),
(1,0,9),
(1,0,10),
(1,2,1),
(1,2,2),
(1,2,4),
(1,4,1),
(1,4,3),
(1,4,4),
(1,5,1),
(1,5,3),
(1,5,5),
(1,6,1),
(1,6,5),
(1,6,6)
Then do the collect:
select
merchant_id,
week_id,
collect_set(acc_id) over (partition by merchant_id ORDER BY week_id RANGE BETWEEN 4 preceding AND 0 preceding) as uniq_accs_prev_4_weeks
from
table_test_test
The result table is :
merchant_id week_id uniq_accs_prev_4_weeks
1 1 0 []
2 1 0 []
3 1 0 []
4 1 2 [9,8,10]
5 1 2 [9,8,10]
6 1 2 [9,8,10]
7 1 4 [9,8,10,1,2,4]
8 1 4 [9,8,10,1,2,4]
9 1 4 [9,8,10,1,2,4]
10 1 5 [1,2,4,3]
11 1 5 [1,2,4,3]
12 1 5 [1,2,4,3]
13 1 6 [1,2,4,3,5]
14 1 6 [1,2,4,3,5]
15 1 6 [1,2,4,3,5]
As you can see, there are redundant rows in the table. This is just an example, in my actual case this table is huge and the redundancy causes memory problem.
I have tried using distinct and group by but neither of these works.
Is there a good way to do it? Thanks a lot.
Distinct works good:
select distinct merchant_id, week_id, uniq_accs_prev_4_weeks
from
(
select
merchant_id,
week_id,
collect_set(acc_id) over (partition by merchant_id ORDER BY week_id RANGE BETWEEN 4 preceding AND current row) as uniq_accs_prev_4_weeks
from
table_test_test
)s;
Result:
OK
1 0 [9,8,10]
1 2 [9,8,10,1,2,4]
1 4 [9,8,10,1,2,4,3]
1 5 [1,2,4,3,5]
1 6 [1,2,4,3,5,6]
Time taken: 98.088 seconds, Fetched: 5 row(s)
My Hive does not accept 0 preceding, I replaced with current row. It seems like this bug or this bug, my Hive version is 1.2. Yours should work fine with distinct added in the upper subquery.

Using sum in Oracle SQL view to add column total in each row

i have a simple Oracle View with 3 columns team, minors, adults as follows:-
create view main_summary ( team, minors, adults)
as
select all_teams.team_name as team ,
case when age<18 then count(id) as minors,
case when age>= 18 then count(id) as adults
from all_teams ;
a select statement return rows like:-
-----------------------------
team | minors | adults
-----------------------------
volleyball 2 4
football 6 3
tennis 4 8
-------------------------------
i want to add a total column in the end which should make the view look like:-
--------------------------------------
team | minors | adults| total
--------------------------------------
volleyball 2 4 6
football 6 3 9
tennis 4 8 12
-----------------------------------------
i tried following, but nothing worked:-
create view main_summary( team, minors, adults, sum(minors+adults)) ...
and
create view main_summary ( team, minors, adults, total)
as
select all_teams.team_name as team ,
case when age<18 then count(id) as minors,
case when age>= 18 then count(id) as adults
sum ( case when age<18 then count(id) +
case when age>= 18 then count(id) ) as total ...
The syntax may not be correct as i am not copying directly from my Database. However, pseudo code remains the same. Please guide me how to achieve this.
I have no idea why your original view works. I think you want:
create view main_summary as
select t.team_name as team ,
sum(case when age < 18 then 1 else 0 end) as minors,
sum(case when age >= 18 then 1 else 0 end) as adults,
count(*) as total
from all_teams
group by t.team_name;

Increment column A when column B changes value

I'm using PL/SQL (Oracle) and this is the result I have from a simple select query at the moment (with an order by):
Name Hour Value
---------------------------------
Peter 1 10
Peter 2 12
Peter 3 22
Joe 1 8
Joe 2 8
Joe 3 12
Richard 1 9
Richard 2 7
Matt 1 11
In SSRS, I have a complex Matrix where I want to have alternating row colors*. Therefor, I need the rownumber, but it must be 'grouped' by the Name. So this is what I want:
Name Hour Value Row_Num
--------------------------------------------
Peter 1 10 1
Peter 2 12 1
Peter 3 22 1
Joe 1 8 2
Joe 2 8 2
Joe 3 12 2
Richard 1 9 3
Richard 2 7 3
Matt 1 11 4
Notice how the Row_Num (or whatever you want to call it) only changes when the Name changes. Is this possible in PL/SQL?
*I know of the techniques to get alternating row colors in SSRS, but I'm using a matrix and have the problem mentioned by Kyle Hale in the comments to ahmad's answer to this question.
This is easy to do with the dense_rank() function in the query used to fetch the results:
select name, hour, value,
dense_rank() over (order by name) as row_num
from t;
Note: this will not necessarily assign the values in the order you have given. But each group will get a different value. If you need them in the order given, then you will need to identify the order. SQL tables are inherently unordered, so a column is needed to specify the ordering.
select name
, value
, hour
, dense_rank() over (partition by 1 order by name) as row_num
from
(
select 'Peter' name, '1' hour , '10' value from dual union all
select 'Peter', '2', '12' from dual union all
select 'Peter', '3', '22' from dual union all
select 'Joe', '1', '8' from dual union all
select 'Joe', '2', '8' from dual union all
select 'Joe', '3', '12' from dual union all
select 'Richard','1', '9' from dual union all
select 'Richard','2', '7' from dual union all
select 'Matt', '1', '11' from dual
)
Joe 8 2 1
Joe 12 3 1
Joe 8 1 1
Matt 11 1 2
Peter 22 3 3
Peter 12 2 3
Peter 10 1 3
Richard 9 1 4
Richard 7 2 4

Resources