Which hotel has the most stayings? - oracle

I am pretty new at Oracle, and I am doing some examples which I found on one of the websites to learn something new. One of the tasks is to get from tables, which hotel has the most stayings. I find this one problem realy complex and I can not solve it by myself, so I Will be happy if someone could help me with soultion and explanation why is is that way.
I understood that question in that way, that you have to connect VISITOR, VISITED, HOTEL, OWNING and OWNER tables.
To explain. OWNING table is connecting OWNERs with their HOTELs and VISITED table is connecting VISITORs with HOTEL in which they stayed.
This are my tables for that example: Pastebin link to my example.
What I have tried so far is:
SELECT visitor.id, visitor.name, visitor.surname, hotel.name
FROM visitor
LEFT JOIN visiting
ON visitor.id = visiting.tk_visitor
LEFT JOIN hotel
ON hotel.id = visiting.tk_hotel
ORDER BY hotel.id ASC;
This is connecting three tables, so I get Visitors and Hotels connected in one table, but i can't go further.
I hope that Will be able to help me, so I can learn something new on that example.
Thanks in addition!

which hotel has the most stayings[?]
Each visit corresponds to one row in table visited, therefore you want to count rows of visited on a per-hotel basis. That's this:
select tk_hotel, count(*) as visits
FROM visited
GROUP BY tk_hotel
If you want only the one (one of the ones) with the most visits then you can order the results by visit count, and take only the first. To get the name of the hotel instead of just its id, you should join the previous result to the hotel table:
SELECT h.name, mv.visits
FROM (
SELECT tk_hotel, count(*) as visits
FROM visited
GROUP BY tk_hotel
ORDER BY count(*) DESC
) mv
JOIN hotel h ON h.id = mv.tk_hotel
WHERE ROWNUM = 1
;
Update
If instead you want all the rows having the maximum number of visits, then that's a different kettle of fish. Here's a way to express it:
WITH visit_count AS (
SELECT tk_hotel, count(*) as visits
FROM visited
GROUP BY tk_hotel
)
SELECT h.name, vc.visits
FROM
hotel h
JOIN visit_count vc ON h.id = vc.tk_hotel
WHERE vc.visits = (SELECT MAX(visits) FROM visit_count)

Related

I'd like to return a single row in a query that joins two tables through a one to many relationship

This is an oracle system. I have a client table (one) and an account table (many). Frankly, I really just want to query the client table but due to poor design, there is a data element that I need for the client table that is only present on the account table - it will be the same value for all accounts for that client so I really just need to return one account row but I'm having problems accomplishing this. Here is the query I tried:
Select
c.client_num,
c.client_name,
a.agency_value
from client c
inner join account a on c.client_num = a.client_num
where a.account_num in (select a2.account_num from account a2 where rownum = 1)
You need to explicitly designate how to pick one record out of many. Here's one method - use MAX
Select
c.client_num,
c.client_name,
(SELECT
MAX(a.agency_value) agency_value
FROM account a
where c.client_num = a.client_num
-- not sure if this line is required - if not please remove
and a.account_num in (select a2.account_num from account a2 where rownum = 1)
) agency_value
from client c
Keep in mind that by implementing this you are "cementing" your bad table design.
Are you absolutely certain that there is only ever one agency_value? use query to find any clients that have more than one agency:
SELECT
a.client_num,
COUNT(DISTINCT a.agency_value) CountOfAgencyValues,
MAX(a.agency_value) max_agency_value,
MIN(a.agency_value) max_agency_value
FROM account a
GROUP BY a.client_num
HAVING COUNT(DISTINCT a.agency_value) > 1
With your input and doing some playing around on my own, here is the code that ultimately addressed my need:
select
c. client_num,
(select a.agency_value
from account a
where a.client_num = c.client_num
and rownum = 1)
from client c

Better solution than left join subqueries?

TablePatient.Patient_ID(PK)
TableProviders.Encounter (joins to PK)
TableProviders.Provider_Type
TableProviders.Provider_ID
TableNames.Full_Name
TableNames.Provider_ID (joins to Table Names)
I want a query that will give, for all the Patient_IDs, the Full_Name of the provider for every Provider ID.
There are about 30 provider_types.
I have made this already using a left join a ton of left joins. It takes a long time to run and I am thinking there is a trick I am missing.
Any help?
Ok, my previous answer didn't match at all what you meant. You want to pivot the table to have on each line one Patient_ID with every Full_name for every provider_type. I assume that each patient has only one provider for one type and not more ; if more, you will have more than one row for each patient, and anyway I don't think it's really possible.
Here is my solution with pivot. The first part is to make it more understandable, so I create a table named TABLE_PATIENT in a subquery.
WITH TABLE_PATIENT AS
(
SELECT TablePatient.Patient_ID,
TableProviders.Provider_Type,
TableNames.Full_Name
FROM TablePatient LEFT JOIN
TableProviders on TablePatient.Patient_ID = TableProviders.Encounter
LEFT JOIN
TableNames on TableNames.Provider_ID = TableProviders.Provider_ID
group by TablePatient.Patient_ID,
TableProviders.Provider_Type,
TableNames.Full_Name
)
SELECT *
FROM TABLE_PATIENT
PIVOT
(
min(Full_name)
for Provider_type in ([type1], [type2],[type3])
) AS PVT
So TABLE_PATIENT just has many rows for each patient, with one provider each row, and the pivot puts everything on a single row. Tell me if something doesn't work.
You need to write every type you want in the [type1],[type2] etc. Just put them inside [], no other character needed as ' or anything else.
If you put only some types, then the query will not show providers of other types.
Tell me if something doesn't work.
If I understand what you mean, you just want to group the answer by Patient Id and then Provider ID. A full name is unique on a provider id right ?
This should be something like
SELECT TablePatient.Patient_ID,
TableProviders.Provider_ID,
TableNames.Full_Name
FROM TablePatient LEFT JOIN
TableProviders on TablePatient.Patient_ID = TableProviders.Encounter
LEFT JOIN
TableNames on TableNames.Provider_ID = TablerProviders.Provider_ID
group by TablePatient.Patient_ID,
TableProviders.Provider_ID,
TableNames.Full_Name
You can either group by TableNames.Full_Name or select First(TableNames.Full_Name) for example if indeed a full name is unique to a provider ID.
Note : I used the SQL server Syntax, there can be différences with Oracle ..

Creating database view in migration laravel 5.2

I'm trying to create a database view via a migration in Laravel 5.2 as I need to hand a fairly complex query to a view. I have models / tables for leagues, teams, players, and points. Each one has a hasMany / belongsTo relationship with the one before it. The goal is to create a table where each row is a league name, a sum of all remaining points for the league, and a count of points.remnants where the value of points.remnants > 4.
Major Edit:
What I have so far is
DB::statement( 'CREATE VIEW wones AS
SELECT
leagues.name as name,
sum(points.remnants) as trem,
count(case when points.remnants < 4 then 1 end) as crem
FROM leauges
JOIN teams ON (teams.league_id = leagues.id)
JOIN players ON (players.team_id = teams.id)
JOIN points ON (points.player_id = players.id);
' );
This does not throw any errors, but it only returns one row and the sum is for all points in all leagues.
What I'm looking for is to create a table where there is a row for each league, that has league name, total remaining points for that league, and total points with less than 4 remaining per league.
Marked as solved. See the accepted answer for most of this issues. The one row problem was because I wasn't using GROUP BY with the count().
It looks to me like the problem is your SQL syntax. Here's what you wrote:
CREATE VIEW wones AS SELECT (name from leagues) AS name
join teams where (leagues.id = team.country_id)
join players where (teams.id = players.team_id)
join points where (players.id = points.player_id)
sum(points.remnants) AS trem
count(points.remnants where points.remnants < 4) AS crem
The problem is with the way you've mixed FROM and JOIN clauses with column specifications. Try this:
CREATE VIEW wones AS
SELECT
leagues.name,
sum(points.remnants) AS trem
sum(IF(points.remnants<4, 1, 0)) AS crem
FROM leagues
JOIN teams ON (leagues.id = team.country_id)
JOIN players ON (teams.id = players.team_id)
JOIN points ON (players.id = points.player_id);
I've reformatted it a bit to make it a little clearer. The SQL keywords are capitalized and the various clauses are separated onto their own lines. What we're doing here is specifying the columns, followed by the table specifications - first the leagues table, then the other tables joined to that one.

Display all the fields associated with the record using Impala

Suppose, I have a student table with some fields in impala. Imagine there is a field called total_mark and I should find the student details with maximum mark from each branch.
My table is like this :-
In this table I have to get the details of student with maximum marks from each department.
My query will be like this :-
select id,max(total_marks) from student_details group by department;
But using this query I can get only the id and total_marks. Provided there can be students with same name,age I can't group with fields like age,name .
So how should I query the table to get all the details of top student from each department ??
Thanks in advance.
You can make use of the JOIN concept
select stu.*
from student_details stu
join
( select department,max(total_marks) as max
from student_details
group by department
) rank
on stu.department=rank.department and stu.total_marks=rank.max;

Oracle relational database, querying/joining multiple tables

I know most people here tend to frown on people asking homework questions on here, but I am really stumped on one question in my database systems class.
List all cities (city name and zip code where there is at least one property for rent managed by staff who works in the branch office at ‘1119 Leighton Ave’. Order your result by ascending order of city name. Otherwise, zero point.
The database schema is:
Branch (bNo, street, zipcode)
Staff (sNo, fName, lName, position, sex, dob, salary, bNo)
Property (pNo, street, zipcode, type, room, rent, oNo, sNo, bNo)
Owner (oNo, fName, fName, street, zipcode, phone)
Client (cNo, fName, lName, phone, prefType, maxRent)
Viewing (pNo, cNo, viewDate, cmmt)
Zip (city, state, zipcode)
And this is the query that I have tried to put together, very unsuccessfully...
SELECT z.city, p.zipcode
FROM Zip z, Property p
WHERE p.bNo = (SELECT bNo
FROM Branch
WHERE street = '1119 Leighton Ave');
I am having a bit of hard time with the joins. This statement above does NOT even come close to working right. I am digging through my book and the internet, trying to find some sort of help. Any help would be greatly appreciated. Thanks in advance.
UPDATE
I am currently trying:
SELECT DISTINCT Zip.city, Zip.zipcode AS Zip
FROM Zip
JOIN Property ON Zip.zipcode = Property.zipcode
JOIN Branch ON Zip.zipcode = Branch.zipcode
WHERE Property.bNo = (SELECT bNo
FROM Branch
WHERE Street = '1119 Leighton Ave')
ORDER BY Zip.city;
The output looks a lot better, but I don't think it is correct. I am checking it now.
UPDATE #2
Okay, so by running this query:
SELECT DISTINCT zipcode
FROM Property
WHERE bNo = 'B001';
and just as an FYI B001 is the branch number for the Branch located at 1119 Leighton Ave. Anyways, that command gave me the following zip codes:
36205
36251
36264
36206
36277
36272
36265
36203
36201
When I run the above command:
SELECT DISTINCT Zip.city, Zip.zipcode AS Zip
FROM Zip
JOIN Property ON Zip.zipcode = Property.zipcode
JOIN Branch ON Zip.zipcode = Branch.zipcode
WHERE Property.bNo = (SELECT bNo
FROM Branch
WHERE Street = '1119 Leighton Ave')
ORDER BY Zip.city;
This is my output:
City Zip
--------------------- -----
ANNISTON 36206
JACKSONVILLE 36265
So, I believe that something is a little off with this query. But you guys have given me a GREAT start, I will continue playing with it and I am confident that I can probably figure it out. Thanks a ton guys.
I think I got it figured out thanks to all the help from everyone.
SELECT DISTINCT Zip.city, Zip.zipcode AS Zip
FROM Zip
JOIN Property ON Zip.zipcode = Property.zipcode
JOIN Branch ON Zip.zipcode = Property.zipcode
JOIN Staff ON Staff.bNo = Branch.bNo
WHERE Property.bNo = (SELECT bNo FROM Branch WHERE Street = '1119 Leighton Ave')
ORDER BY Zip.city
There are multiple ways to write JOIN queries in Oracle. A more standard SQL way is to do something like this:
SELECT t1.colNameA, t1.colNameB, t2.colNameC
FROM t1
JOIN t1.pid = t2.fkid
WHERE
t1.colNameA='whatever'
With that in mind, you might try the following steps:
List out all the columns that you need:
SELECT Zip.city, Zip.zipcode
List out all the tables that you need, including the relationships
between them:
FROM Zip
JOIN Property ON Zip.zipcode=Property.zipcode
JOIN Branch ON Zip.zipCode=Branch.zipcode
JOIN etc
Add the WHERE criteria.
WHERE Branch.street='1119 LeightonAve'
AND etc
Add ORDER BY clause
ORDER BY Zip.city
This is not the complete answer, but hopefully helps get you in the right direction.
EDIT #2
After your edit, I would suggest you need to research the keyword "DISTINCT". Something like this might be more what you are looking for:
SELECT DISTINCT Zip.city, Zip.zipcode
Try this
SELECT z.city, p.zipcode
FROM Zip z
JOIN Property p ON z.zipcode = p.zipcode -- city name and zip code where there is at least one property for rent
JOIN Staff s ON p.sNo = p.sNo -- managed by staff
JOIN Branch b ON s.bNo = b.bNo AND b.street = '1119 Leighton Ave' -- who works in the branch office at ‘1119 Leighton Ave’
ORDER BY z.city
JOIN(INNER JOIN) makes sure both table participating has the same value in at least one row, otherwise no record is returned.

Resources