Grouping based on a category from Table - oracle

i have a specific scenario where the subtotals and totals would need to be shown based on a selection parameter .
So the table has players and their attributes as shown below .
The user can select any or combination of the TYPE fields .
Below is the query result needed when TYPEA and TYPED are selected.
Below is the query when TYPEB and TYPEC are selected.
The user can select 3 TYPE or 4 type fields for which subtotals and totals are needed.
Any assistance is highly appreciated.

You can do this using rollup or grouping sets in sqlplus with break:
break on TYPEA skip 1 on TYPEB skip 1 on TYPEC on TYPED;
with t(runs, run_percentage, name, typea, typeb, typec, typed) as (
select 50, 22.22222 , 'PLAYER1', 'BAT' , 'RIGHT', 'OPENER' , 'TALL' from dual union all
select 45, 20 , 'PLAYER2', 'BAT' , 'RIGHT', 'OPENER' , 'TALL' from dual union all
select 40, 17.77778 , 'PLAYER3', 'BAT' , 'LEFT' , 'OPENER' , 'TALL' from dual union all
select 35, 15.55556 , 'PLAYER4', 'BAT' , 'LEFT' , 'STRIKER' , 'SHORT' from dual union all
select 30, 13.33333 , 'PLAYER5', 'BOWL' , 'RIGHT', 'OPENER' , 'TALL' from dual union all
select 25, 11.11111 , 'PLAYER6', 'BOWL' , 'RIGHT', 'STRIKER' , 'SHORT' from dual
)
select
typea, typeb, typec, typed
,sum(runs) runs
from t
group by rollup (typea, typeb, typec, typed);
Results:
TYPE TYPEB TYPEC TYPED RUNS
---- ----- ------- ----- ----------
BAT LEFT OPENER TALL 40
40
STRIKER SHORT 35
35
75
RIGHT OPENER TALL 95
95
95
170
BOWL RIGHT OPENER TALL 30
30
STRIKER SHORT 25
25
55
55
225
16 rows selected.
More examples of rollup and grouping sets

Related

How to get records based on most occurring value?

I have following table and I want to get records where promotion is mostly occurring.
For example if I got two events
FREQ_VISITOR, value= 250
HIGH_SHOPPER, value= 320
Then Promo 1 and Promo 2 should come in result. Since these 2 promos exists mostly for every trigger and their given values.
Here's one option, based on what I understood:
SQL> with test (event_name, value, promotion) as
2 (select 'freq_visitor', 250, 'promo1' from dual union all
3 select 'high_shopper', 320, 'promo2' from dual union all
4 select 'freq_visitor', 250, 'promo3' from dual union all
5 select 'high_shopper', 320, 'promo1' from dual union all
6 select 'freq_visitor', 250, 'promo2' from dual
7 ),
8 cnt_promo as
9 (select promotion, count(*) cnt
10 from test
11 group by promotion
12 ),
13 most_promos as
14 (select max(cnt) max_cnt
15 from cnt_promo
16 )
17 select c.promotion
18 from cnt_promo c join most_promos m on c.cnt = m.max_cnt;
PROMOT
------
promo1
promo2
SQL>
This is a good candidate for analytic functions.
The below code is a bit longer than the self-join approach, and flows from the inside-out instead of a more traditional top-to-bottom direction. But this approach will likely be faster, since it only reads from the table once. And this approach is easier to debug than common table expressions, since you can highlight and run different inline views and watch the result set be built.
--Promotions with the highest counts.
select promotion
from
(
--RANK the promotion counts.
select promotion, promotion_count,
rank() over (order by promotion_count desc) promotion_rank
from
(
--Count of promos per event and value.
select promotion, count(*) promotion_count
from
(
--Test data
select 'freq_visitor' event_name, 250 value, 'promo1' promotion from dual union all
select 'high_shopper' event_name, 320 value, 'promo2' promotion from dual union all
select 'freq_visitor' event_name, 250 value, 'promo3' promotion from dual union all
select 'high_shopper' event_name, 320 value, 'promo1' promotion from dual union all
select 'freq_visitor' event_name, 250 value, 'promo2' promotion from dual
) test_data
group by promotion
) add_promo_count
) add_promo_rank
where promotion_rank = 1
order by promotion;

Oracle: Getting highest value from two fields (date then value)

I have something like this (date simplified to integer just for the example):
Order Date Value
12 5 555
12 5 800
12 2 900
13 3 122
13 4 155
14 1 121
... ... ...
And I'd like to get the order with the highest date and then the highest value:
Order Date Value
12 5 800
13 4 155
14 1 121
... ... ...
I know this is similar to several other questions but cant figure out how to apply those answers to my case, sorry.
Thanks!
Use analytic function ROW_NUMBER
SELECT "Order", "Date", "Value"
FROM (
select t.*,
row_number()
over (partition by "Order" order by "Date" desc, "Value" desc ) As rn
FROM table1 t
) x
WHERE rn = 1
You can use the analytic FIRST/LAST function (see Oracle documentation). This solution does not need the subquery/outer query arrangement. I changed the column names since at least ORDER and DATE are Oracle keywords.
with
inputs ( ord, dt, val ) as (
select 12, 5, 555 from dual union all
select 12, 5, 800 from dual union all
select 12, 2, 900 from dual union all
select 13, 3, 122 from dual union all
select 13, 4, 155 from dual union all
select 14, 1, 121 from dual
)
-- End of test data (not part of the solution).
-- SQL query begins BELOW THIS LINE
select ord, max(dt) as dt, max(val) keep (dense_rank last order by dt) as val
from inputs
group by ord
;
ORD DT VAL
--- -- ---
12 5 800
13 4 155
14 1 121
Lets assume your table name is orders
In a subquery you find orders with highest dates and for those you find highest values... It will look like this:
select order,date,max(value) value from orders
where (order,date) in
(select order, max(date) date
from orders
group by order
)
group by order,date
order by order,date desc

Oracle SQL Select Query Getting Max Row As a Fraction of a Rollup Total

hoping I might be able to get some advise regarding Oracle SQL…
I have a table roughly as follows (there are more columns, but not necessary for this example)…
LOCATION USER VALUE
1 1 10
1 2 20
1 3 30
2 4 10
2 5 10
2 6 20
1 60
2 40
100
I’ve used rollup to get subtotals.
What I need to do is get the max(value) row for each location and express the max(value) as a percentage or fraction of the subtotal for each location
ie:
LOCATION USER FRAC
1 3 0.5
2 6 0.5
I could probably solve this using my limited knowledge of select queries, but am guessing there must be a fairly quick and slick method..
Thanks in advance :)
Solution using analytic functions
(Please note the WITH MY_TABLE AS serving only as dummy datasource)
WITH MY_TABLE AS
( SELECT 1 AS LOC_ID,1 AS USER_ID, 10 AS VAL FROM DUAL
UNION
SELECT 1,2,20 FROM DUAL
UNION
SELECT 1,3,30 FROM DUAL
UNION
SELECT 2,4,10 FROM DUAL
UNION
SELECT 2,5,10 FROM DUAL
UNION
SELECT 2,6,20 FROM DUAL
)
SELECT LOC_ID,
USER_ID,
RATIO_IN_LOC
FROM
(SELECT LOC_ID,
USER_ID,
RATIO_IN_LOC,
RANK() OVER (PARTITION BY LOC_ID ORDER BY RATIO_IN_LOC DESC) AS ORDER_IN_LOC
FROM
(SELECT LOC_ID,
USER_ID,
VAL,
VAL/SUM(VAL) OVER (PARTITION BY LOC_ID) AS RATIO_IN_LOC
FROM MY_TABLE
)
)
WHERE ORDER_IN_LOC = 1
ORDER BY LOC_ID,
USER_ID;
Result
LOC_ID USER_ID RATIO_IN_LOC
1 3 0,5
2 6 0,5
with inputs ( location, person, value ) as (
select 1, 1, 10 from dual union all
select 1, 2, 20 from dual union all
select 1, 3, 30 from dual union all
select 2, 4, 10 from dual union all
select 2, 5, 10 from dual union all
select 2, 6, 20 from dual
),
prep ( location, person, value, m_value, total ) as (
select location, person, value,
max(value) over (partition by location),
sum(value) over (partition by location)
from inputs
)
select location, person, round(value/total, 2) as frac
from prep
where value = m_value;
Notes: Your table exists already? Then skip everything from "inputs" to the comma; your query should begin with with prep (...) as ( ...
I changed user to person since user is a keyword in Oracle, you shouldn't use it for table or column names (actually you can't unless you use double quotes, which is a very poor practice).
The query will output two or three or more rows per location if there are ties at the top. Presumably this is what you desire.
Output:
LOCATION PERSON FRAC
---------- ---------- ----------
1 3 .5
2 6 .5

Oracle PIVOT a select statement

I would like to pivot a select statement.
Columns "Country", "Store" and "Sales" are given.
Now I would like to have an output like:
Store1 Store2 Store3
Country1 2342 2342 5675
Country2 5753 3274 7326
Country3 1543 4367 3367
So basically I need the salescount for every Store, for every Country.
The Input comes from (example):
Country: StoreNr: ProductSold:
Belgium 23 Car
Belgium 23 House
Netherland 23 Car
Output would be:
Store23
Belgium 2
Netherlands 1
If the number of stores is finite, you could use one of these approaches:
Using count() aggregate function combined with case expression:
-- sample of data. just for the sake of demonstration
SQL> with t1(Country, StoreNr, ProductSold) as(
2 select 'Belgium' , 23, 'Car' from dual union all
3 select 'Belgium' , 23, 'House' from dual union all
4 select 'Netherland', 23, 'Car' from dual union all
5 select 'Belgium' , 25, 'House' from dual
6 )
7 select country
8 , count(case
9 when StoreNr = 23
10 then 1
11 end) as storeNr_23
12 , count(case
13 when StoreNr = 25
14 then 1
15 end) as storeNr_25
16 from t1
17 group by country
18 ;
Result:
COUNTRY STORENR_23 STORENR_25
---------- ---------- ----------
Belgium 2 1
Netherland 1 0
Starting from Oracle 11g and up, the pivot operator as follows:
select *
from (Select country as country
, country as country_cnt
, StoreNr
from t1)
pivot( -- list all store numbers here
count(country_cnt) for storenr in ( 23 as StoreNr_23
, 25 as StoreNr_25)
)
Result:
COUNTRY STORENR_23 STORENR_25
---------- ---------- ----------
Belgium 2 1
Netherland 1 0

Combining column values from different tables

I stuck. I have 2 tables - look at image no.1 Table columns And i would like to build query, that will give me the result - it is showed on image no 2. the result of query.
I have 2 queries and I would like to mix them up, to obtain the list from image no.2. Please help me, how to build a query.
Query no1: SELECT department_name, department_id FROM DEPARTMENTS WHERE department_id between 90 AND 110;
Query no 2: SELECT last_name, department_id from employees WHERE department_id between 90 AND 110;
Query:
with departments (department_id, department_name) as (
select 90, 'Executive' from dual union all
select 100, 'Finance' from dual union all
select 110, 'Accounting' from dual
),
employees (employee_id, last_name, department_id) as (
select 1003, 'King' , 90 from dual union all
select 1005, 'De Hann' , 90 from dual union all
select 1009, 'Gietz' , 110 from dual union all
select 1013, 'Popp' , 100 from dual union all
select 1014, 'Chen' , 100 from dual union all
select 1015, 'Higgins' , 110 from dual union all
select 1029, 'Greenberg', 100 from dual union all
select 1040, 'Kochar' , 90 from dual union all
select 1043, 'Faviet' , 100 from dual union all
select 1045, 'Urman' , 100 from dual union all
select 1049, 'Sciarra' , 100 from dual
)
-- end input data; begin actual query --
select c_name, department_id from
( select department_name as c_name, department_id, 0 as categ from departments
union all
select ' ' || last_name as c_name, department_id, 1 from employees
order by department_id, categ, c_name
);
Result:
C_NAME DEPARTMENT_ID
------------- -------------
Executive 90
De Hann 90
King 90
Kochar 90
Finance 100
Chen 100
Faviet 100
Greenberg 100
Popp 100
Sciarra 100
Urman 100
Accounting 110
Gietz 110
Higgins 110
You don't need the "with ..." part; just use the query that begins at the SELECT statement after the two factored subqueries (after the "input data"). I even ordered by last name within each department for you; if that is not needed, just delete "c_name" from the ORDER BY clause.
I called the first column c_name; you may call it whatever you want, but calling it department_name when it also holds employee last names didn't make much sense to me. To call it whatever you want, change the SELECT statement from SELECT c_name, department_id to SELECT c_name AS whatever, department_id...
SELECT c.last_name,
d.department_id,
d.department_name
FROM employee c
JOIN deptartment d ON d.department_id=c.department_id
WHERE d.department_id BETWEEN 90 AN 110
OUTPUT from my sample table
+-------+----+------------+
| KING | 10 | ACCOUNTING |
| BLAKE | 30 | SALES |
| CLARK | 10 | ACCOUNTING |
| JONES | 20 | RESEARCH |
| SCOTT | 20 | RESEARCH |
+-------+----+------------+

Resources