Limiting records and putting restrictions - sql

What i want to do is, display all the rooms having capacity to accommodate students, In Rooms table it has a field "Capacity", in which Number of students that can be accommodate is specified,
My idea was to select all the records of the students and check them if more then prescribed limit of student records are found against "capacity " Column in any room, then App shouldn't allow user to insert the record, but i don't know how do i do it. I gotta accommodate students in rooms in a way that it must not accommodate a student in any room if the number of students accommodated in that room exceeds the available seats.
what i tried:
select Student.StudentName,Student.RoomNumber,Rooms.RoomID
From Student
INNER JOIN Rooms
ON Student.RoomNumber=Rooms.RoomId,
that's what i get and that's not what i need,
so what i need is, jawad,hamid,asim are residents of room one which has the capacity to accomodate 3 students only, what i adversly want is to display the rooms which do have capacity to accomodate new students, and if theere are more student records associated with a room record more then it's capacity then user must not be allowed to assign that room to a student.

You can group by the room:
select r.RoomNumber,
r.Capacity,
r.Capacity - count(s.Name) as RemainingCapacity
from Students s
join Rooms r
on r.RoomNumber = s.RoomNumber
group by r.RoomNumber, r.Capacity
This shows:
RoomNumber Capacity RemainingCapacity
1 2 1
2 3 -1
With these values:
Students:
Name RoomNumber
B 1
C 2
D 2
E 2
F 2
Rooms:
RoomNumber Capacity
1 2
2 3

select Student.StudentName,Student.RoomNumber
where Student.RoomNumber IN
( select Student.RoomNumber
From Student
INNER JOIN Rooms
ON Student.RoomNumber=Rooms.RoomId
Group by Student.RoomNumber, Rooms.Capacity
having COUNT(Student.RoomNumber) <= Rooms.Capacity) t

Related

Count the number of occurences in each bucket Redshift SQL

This might be difficult to explain. But Im trying to write a redshift sql query where I have want the count of organizations that fall into different market buckets. There are 50 markets. For example company x can be only be found in 1 market and company y can be found in 3 markets. I want to preface that I have over 10,000 companies to fit into these buckets. So ideally it would be more like, hypothetically 500 companies are found in 3 markets or 7 companies are found in 50 markets.
The table would like
Market Bucket
Org Count
1 Markets
3
2 Markets
1
3 Markets
0
select count(distinct case when enterprise_account = true and (market_name then organization_id end) as "1 Market" from organization_facts
I was trying to formulate the query from above but I got confused on how to effectively formulate the query
Organization Facts
Market Name
Org ID
Org Name
New York
15683
Company x
Orlando
38478
Company y
Twin Cities
2738
Company z
Twin Cities
15683
Company x
Detroit
99
Company xy
You would need a sub-query that retrieves the number of markets per company, and an outer query that summarises into a count of markets.
Something like:
with markets as (
select
org_name,
count(distinct market_name) as market_count
from organization_facts
)
select
market_count,
count(*) as org_count
from markets
group by market_count
order by market_count
If I follow you correctly, you can do this with two levels of aggregation. Assuming that org_id represents a company in your dataset:
select cnt_markets, count(*) cnt_org_id
from (select count(*) cnt_markets from organization_facts group by org_id) t
group by cnt_markets
The subquery counts the number of markets per company. I assumed no duplicate (ord_id, market_name) tuples in the table ; if that's not the case, then you need count(distinct market_name) instead of count(*) in that spot.
Then, the outer query just counts how many times each market count occurs in the subquery, which yields the result that you want.
Note that I left apart the enterprise_account column ,that appears in your query but not in your data.

SQL oracle: Display records that are not found in another table

I have tried to fetch a record that will return me with the doctor's ID and the total number of all the prescriptions they have given.
SELECT doc.DID, COUNT(pr.DID)
FROM DOCTOR doc, PRESCRIPTION pr
WHERE doc.DID = pr.DID
GROUP BY doc.DID;
By using this statement, I am able to receive the information as long as there is at least one prescription made by a doctor. This is how my results looks like
DID COUNT(PR.DID)
-------------------- -------------
3292848 1
3292885 10
3293063 10
3332949 15
3332950 2
But I want it to display such that even doctors that has not prescribed before will be shown in the record with a count of 0
DID COUNT(PR.DID)
-------------------- -------------
3292848 1
3292885 10
3293042 0
3293063 10
3332949 15
3332950 2
334021 0
First of all, please avoid using old join syntax. Use proper JOIN syntax.
Now here you need a LEFT JOIN which would give you everything from first table and matching records from second table. For non matching records, you will get null, which you can utilize in where or select clause.
SELECT doc.DID, COUNT(pr.DID)
FROM DOCTOR doc
left join
PRESCRIPTION pr
on doc.DID = pr.DID
GROUP BY doc.DID;

How to link the relational datatables and divide the sum of 3 columns from one table by 1 column in another table using SQL SELECT query

I'm creating a database for Formula 1 drivers/teams. The idea is to display the cost comparisons of team budgets vs team points and driver salaries, to see the effective cost per point for the top 10 teams.
E.g from 2015 info
Team Mercedes
Income received = euro 467.4m (sponsors 122m, partners 212.40m, tv 133m).
Points Scored = 703 (total from both drivers: Hamilton 381, Rosberg 322).
Effective Cost Per Point = 2,506,417.11
I have 3 datatables: One each for the team, the drivers, and a table to join tables 1&2 together, to then create the correct SELECT queries:
Table 'team'
teamid
teamname
sponsors
partners
tv
total
Table 'driver'
driverid
drivername
salary
points
Table 'driverteam'
teamid
driverid
totalbudget
totalpoints
I first need to get the sum of the sponsors,partners and tv so I have created the following SELECT statement:
$sql = "SELECT teamname, sum(sponsors+partners+tv) as total FROM team ORDER BY total DESC LIMIT 10";
I know how to get the salary and points from a driver:
$sql = "SELECT drivername, salary FROM driver ORDER BY salary DESC LIMIT 10";
$sql = "SELECT drivername, points FROM driver ORDER BY points DESC LIMIT 10";
Seems ok, but now comes my problem, how to get the SUM from table 1 and divide it by the points that the drivers have got in table 2.
My limited brain says I need a INNER JOIN using table 3 to get table 1 & 2 together, before performing the necessary divisions etc.
As there are 2 drivers per team, I need to divide the team total budget by each drivers' points, as well as the team total by both drivers points.
What SELECT queries do I need to achieve this?

Can you use data that you got from a query in another query?

Say I've got some data from a SELECT query. Can I use this as a table later, meaning naming it something then using its rows and columns in other queries?
I can't solve this problem for the life of me. I'm a beginner. It's just one table but I just can't get a query working. Here is what I have:
Hotel table and Room table (I'll just need to use the Room table; I mentioned Hotel just as a reference point for understanding).
Room has the following columns: (Number,HID) - this is a composite primary key; Number is the numerical number of the room and HID is the ID of the hotel which it belongs to. I also have one more column, Name. Now the problem is:
Find all the Hotels which only have rooms Named OneBedroom
I tried (and failed) by doing it by selecting all HIDs from Room, then filtering on not exist(hotels that have at least one non-OneBedroom named room), but I couldn't make this work.
Room
Number HID Name
1 H1 OneBedroom
2 H2 OneBedroom
3 H1 OneBedroom
4 H1 OneBedroom
5 H2 TwoBedroom
6 H3 OneBedroom
Desired Output: HID
H1
H3
I suspect something like this would do it
SELECT DISTINCT `hid` FROM `room` WHERE
`room`.`hid` NOT IN
(SELECT `hid` as `hid` FROM `room` WHERE `name` != "OneBedroom");
Untested, might be crap, but seems like it should work. Basically, the inner query gets all hid's of rooms that are not OneBedrooms. We then subtract all of those hid's from a full list of hid's.
The easiest way is using group by plus having with a conditional count, so no need to include aditional subquery.
This return hotel with all room = "OneBedroom", remember COUNT only count values <> NNLL
SELECT `hid`
FROM `room`
GROUP BY `hid`
HAVING COUNT(CASE WHEN `name` != "OneBedroom" THEN 1 END ) = 0
At least one bedroom is call "OneBedroom"`
HAVING COUNT(CASE WHEN `name` = "OneBedroom" THEN 1 END ) >= 1
The default value for CASE is NULL so no need for ELSE part
I'm going with a table like this from what you describe:
table Room
HID Number Name
----------------------------------------
1 101 OneBedroom
1 102 OneBedroom
1 103 TwoBedroom
1 201 Suite
2 101 OneBedroom
2 102 OneBedroom
2 103 OneBedroom
which I assume connects to a table Hotel:
table Hotel
HID name
------------------
1 StayOver
2 SleepTite
Now for the query:
SELECT h.name
FROM Hotel h
WHERE h.HID NOT IN (SELECT r.HID
FROM Room r
WHERE name != 'OneBedroom');
which will give you a list of the hotel names with only one bedroom rooms.
Works on SQLite with sample data. Should be okay.
EDIT - based on edited question:
SELECT h.HID . . .
instead of h.name in above query.

Deriving Data from Multiple Tables & Joining in Oracle

Users will be recording data using the following two tables:
USERS:
UserID UserName UserType
1 Tom 5
2 Mike 6
3 Joe 6
RECORDINGS :
UserID Recording
1 10
1 15
I want to use a single query to find the Name, and the count of recordings made by each user whose UserType is above the average of UserType. In the event a user has never made a recording, it needs to be 0 (not null or missing).
My approach is to first select the users who are above average, second to select the count of recordings made by each user, and third to join the two where UserID matches. Is there a more straight forward approach?
SELECT usr.UserID
,COUNT(rec.Recording) Count
FROM USers usr
,Recordings rec
,(SELECT AVG(UserType) average
FROM USers usr1) avg1
WHERE usr.Userid = rec.userid(+)
AND avg1.average < usr.UserType
GROUP BY usr.UserID
Please check if this works.
http://sqlfiddle.com/#!4/a03d2/5/0