Display only the largest count in a group by statment - oracle

I'm trying to display only the largest group in this group by statement;
SELECT COUNT(type) AS booking, type FROM booking b, room r WHERE r.rno = b.rno AND r.hno = b.hno GROUP BY type;
I modified it so we get this query response now you can see group double is larger then family.
BOOKING TYPE
5 double
2 family
I know there is a HAVING keyword you can add in order display only a count compared to a number so I could do COUNT(type) HAVING > 2 or similar but that's not very dynamic and that would only work in this instance because I know the two amounts.

ORDER BY COUNT(type) DESC LIMIT 1

There isn't a having statement that does this. But you can use rownum with a subquery:
select t.*
from (SELECT COUNT(type) AS booking, type
FROM booking b join
room r
on r.rno = b.rno AND r.hno = b.hno
GROUP BY type
order by count(type) desc
) t
where rownum = 1;

Just order your query..
order by booking desc
regards

TRY this
SELECT COUNT(type) AS booking, type FROM booking b, room r WHERE r.rno = b.rno AND r.hno = b.hno ORDER BY type DESC LIMIT 1

Related

Customer details based on booking count

Write a query to display user id and user name where the number of seats booked by the user in the individual booking is greater than 1. Display records in ascending order by user name.
I have tried this query and I m getting errors. Please help me!!
select u.user_id,u.name
from users u join bookingdetails bd
on u.name=bd.name
join tickets t on u.user_id=t.user_id
group by u.name
having count(t.no_seats) > 1
order by u.name;
select distinct u.user_id,u.name from users u
join tickets t on u.user_id = t.user_id
where
u.user_id in( select user_id from tickets where no_seats>1)
order by u.name;
If I understand your assignment it looks like you should do
WITH cteBookings AS (SELECT bd.USER_ID, SUM(t.NO_SEATS) AS TOTAL_SEATS_BOOKED
FROM BOOKINGDETAILS bd
INNER JOIN PAYMENTS p
ON p.BD_ID = bd.BD_ID
INNER JOIN TICKETS t
ON t.TICKET_ID = p.TICKET_ID
GROUP BY bd.USER_ID)
SELECT DISTINCT b.USER_ID, u.USER_NAME
FROM USERS u
INNER JOIN cteBookings b
ON b.USER_ID = u.USER_ID
WHERE b.TOTAL_SEATS_BOOKED > 1
ORDER BY u.USER_NAME ASC
Best of luck.
According to the question, it asks for the individual bookings > 1
So, the solution is very simple i.e, for each ticket_id, the no of seats should be greater than 1.
SELECT DISTINCT(user_id),name
FROM Tickets inner join Users
USING (user_id)
WHERE no_seats>1
ORDER BY name;
It will simpler if you try it without joins.
A simple example using a subquery:
select user_id, name from users
where user_id = any(select distinct user_id from tickets where no_seats > 1)
order by name asc;

how to select count in oracle

enter image description here
how to count salary where job_title ?
I tried with coding like this, but the result error
this my code
select a.job_id,a.job_title,avg(b.salary) gaji_rata_rata
from jobs a, employees b where a.job_id=b.job_id order by job_id;
You need a group when using aggregation function
select a.job_id,a.job_title,avg(b.salary) gaji_rata_rata
from jobs a, employees b
where a.job_id=b.job_id
group by a.job_id,a.job_title
order by job_id;

ORACLE - MAX and SUM

The below query returns a list of the most popular theatre and rowtype combinations sorted by total amount:
so for example:
NAME ROWTYPE TOTALAMOUNT
theatre1 middle 200
theatre2 front 190
theatre1 front 150
theatre2 middle 100
Whereas what I need is simply the maximum per theatre:
theatre1 middle 200
theatre2 front 190
Query:
SELECT name, rowtype, sum
from ( select
name, rowtype, sum(totalamount) sum from trow, fact, theatre
Where trow.trowid = fact.trowid
AND
theatre.theatreid = fact.theatreid
GROUP BY rowtype, name
)
ORDER BY sum DESC, name, rowtype ;
You can use window functions for this:
select name, rowtype, sum
from (select name, rowtype, sum(totalamount) as sumta,
max(sum(totalamount)) over (partition by name) as maxsumta
from trow join
fact
on trow.trowid = fact.trowid join
theatre
on theatre.theatreid = fact.theatreid
group byrowtype, name
) nr
where sumta = maxsumta;
In addition, you should learn to use proper, explicit JOIN syntax. A simple rule: Never use commas in the FROM clause. Always use proper explicit JOIN syntax.
Put your current query into a common table expression and then use window functions to find the max total amount for each theatre.
WITH cte AS
(
SELECT name, rowtype, SUM(totalamount) sum
FROM trow
INNER JOIN fact
ON trow.trowid = fact.trowid
INNER JOIN theatre
ON theatre.theatreid = fact.theatreid
GROUP BY name, rowtype
)
SELECT name, rowtype, sum
FROM
(
SELECT name,
rowtype,
sum,
MAX(sum) OVER (PARTITION BY name) maxSum
FROM cte
) t
WHERE t.sum = t.maxSum

oracle procedure cursor query when case statement

CURSOR BULKUPDATE IS
SELECT SUM(B.ACCOUNT_BALANCE) AS ACCOUNT_BALANCE,C.CIF AS CIF_ID FROM _ACCOUNTS_STAGING2 B JOIN _RELATION_STAGING2 C
ON B.ACCOUNT_IDENTIFICATION_NUMBER = C.ACCOUNT_IDENTIFICATION_NUMBER AND B.SOURCEID=C.SOURCEID JOIN _CUSTOMER_STAGING2 A ON A.CIF=C.CIF AND A.SOURCEID=C.SOURCEID WHERE C.ROLE_ON_ACCOUNT IN
(Select Rollonaccount From _Roleaccount_Master Where Aggregatebalance='Y')
And upper(B.Scheme_Type) In (Select Scheme_Type From _Schema_Type_Master Where
Depository_Account = 'Y') Group By C.Cif;
Rec_Bulkupdate Bulkupdate%Rowtype;
I am using this query to sum account balances based on different cif and source. The question is I want to calculate four different types of sum on the basis of _Schema_Type_Master. For example I want to check now current_account='Y' instead of Depository_Account='Y'
_ACCOUNTS_STAGING2 B JOIN _RELATION_STAGING2 C
ON B.ACCOUNT_IDENTIFICATION_NUMBER = C.ACCOUNT_IDENTIFICATION_NUMBER AND B.SOURCEID=C.SOURCEID JOIN _CUSTOMER_STAGING2 A ON A.CIF=C.CIF AND A.SOURCEID=C.SOURCEID WHERE C.ROLE_ON_ACCOUNT IN
(Select Rollonaccount From _Roleaccount_Master Where Aggregatebalance='Y')
And upper(B.Scheme_Type) In (Select Scheme_Type From _Schema_Type_Master Where
current_account='Y') Group By C.Cif;
Rec_Bulkupdate Bulkupdate%Rowtype;
Is there any way or do I need to write four different cursors for that??
You can remove dipository_account='Y' and current_account='Y' and use case in select as -
SELECT SUM(CASE WHEN Depository_Account = 'Y' THEN B.ACCOUNT_BALANCE ELSE 0 END) AS DIPOSITORY_ACCOUNT_BALANCE,
SUM(CASE WHEN current_account = 'Y' THEN B.ACCOUNT_BALANCE ELSE 0 END) AS CURRENT_ACCOUNT_BALANCE
and then rest of your code. You will get two different columns for sum of Depository account and Current account.
And if filter for dipository_account='Y' and current_account='Y' is required, then use them in where condition with or operator :
AND (dipository_account='Y' or current_account='Y')

Oracle stored procedure - gradual building of of out variable

I'm sorry for my strange title, but I don't know what exactly I'm looking for. The task is quite simple. I have the table of competitions. Another table groups. In every group there are several contestants. In the last table are stored the results of contestants. The task is to get the first three of the contestants of every group.
So I have to loop through the groups, get the first three contestants (according to achieved points) of every group and append them into some variable.
Here is the pseudocode:
CREATE OR REPLACE PROCEDURE get_first_three_of_all(contestants OUT SOME_TYPE) AS
CURSOR groups SELECT...
BEGIN
FOR group IN groups LOOP
APPEND(contestants, get_first_three_of_one_group(group.id))
END LOOP;
END;
I have no idea, how to solve this task. I even don't know what should I look for. Would you be so kind and help me, please? Thanks.
Edited: simplified structure of my tables:
Competition: competition_id
Contestant: contestant_id
GroupContestant: contestant_group_id, competition_d, group_number, contestant_id
Result: contestant_group_id, juror, points
Select to get data of one group (group number YYY) is here:
SELECT * FROM (
SELECT res.contestant_group_id, SUM(res.points) AS points
FROM Result res
WHERE res.couple_group_id IN (SELECT couple_group_id
FROM GroupContestant
WHERE competition_id = XXX
AND group_number = YYY)
GROUP BY res.contestant_group_id
ORDER BY points DESC
)
WHERE ROWNUM <= 3;
Analytic functions to the rescue. To select top 3 results for each group, each competition:
SELECT * FROM (
SELECT grp.competition_id, grp.group_number, res.contestant_group_id, res.points,
row_number() over (partition by grp.competition_id, grp.group_number
order by res.points desc) rn
FROM (SELECT contestant_group_id, SUM(points) AS points
FROM Result
GROUP BY contestant_group_id) res
JOIN GroupContestant grp ON (grp.contestant_group_id = res.contestant_group_id)
)
WHERE rn <= 3;
Pay attention to how you resolve ties (consider using rank or dense_rank instead of row_number).
You can use RANK() analytic function to achieve the goal:
select *
from (select group_num,
points,
rank() over(partition by group_num order by points desc) rank
from results
inner join group_contestant
using (contestant_group_id))
where rank <= 3
order by group_num, points desc;
Here is SQLFiddle to play with.

Resources