How to make a view with 2 tables linked by another table? - sql

I have 3 table
driver
id
first name
last_name
age
1
Joe
doe
26
2
John
smith
31
...
...
...
...
Location
id
name
zipcode
country
1
London
250 329
UK
2
NY
00501
USA
...
...
...
...
Travel
id
Person_id
location_id
nb_passenger
1
1
1
2
2
1
1
4
3
2
2
3
4
1
2
2
5
2
1
3
...
...
...
...
I'm looking to create a view to get the total number of passengers by destination and by driver, but it's taking the same row multiple times
I tried something like that but it didn't work
SELECT location.id AS location_id,
location.name AS location_name,
d.id AS driver_id,
d.name AS driver_name,
sum(tr.passenger) as passenger_count
FROM location
LEFT JOIN travel tr_0 ON location.id = tr_0.location_id
LEFT JOIN driver d ON tr_0.driver_id = d.id
LEFT JOIN travel tr ON location.id = tr.location_id AND tr.driver_id = d.id
GROUP BY location.id, location.name,...;
I'm sure it's simple but I'm not on the right way

Related

Denormalization table - SQL Select (Pivot Table?)

CAMPAIGN table
ID
campaign_name
1
Campaign A
2
Campaign B
PARTICIPANT table
ID
campaign_id
participant_name
1
1
Alice
2
1
Ben
CUSTOM_FIELD table
ID
campaign_id
field_name
1
1
Gender
2
1
Age
FIELD_ANSWER table
ID
participant_id
field_id
answer
1
1
1
Female
2
1
2
24
3
2
1
Male
4
2
2
28
With these tables in above, can we query a result as shown below?
Campaign Name
Participant Name
Gender
Age
Campaign A
Alice
Female
24
Campaign A
Ben
Male
28
Using pivoting logic we can try:
SELECT
c.campaign_name,
p.participant_name,
MAX(CASE WHEN cf.field_name = 'Gender' THEN fa.answer END) AS Gender,
MAX(CASE WHEN cf.field_name = 'Age' THEN fa.answer END) AS Age
FROM CAMPAIGN c
INNER JOIN PARTICIPANT p
ON p.campaign_id = c.ID
INNER JOIN FIELD_ANSWER fa
ON fa.participant_id = p.ID
INNER JOIN CUSTOM_FIELD cf
ON cf.ID = fa.field_id AND cf.campaign_id = c.ID
GROUP BY
c.campaign_name,
p.participant_name;
Here is a demo in SQL Server, though the above query should run on most other database as well.

Select from table 1 unless there is a relationship in 2 other tables

I need to query a name(s) from the Officials table, but exclude that name if the person has the day blocked.
For example, if Sam has blocked 8/21/2021 and 9/11/2021, he should not be selected if the corresponding dates are selected from the Games table. Sam should show up if 9/18/2021 is selected, however. I have 3 tables:
Officials tbl
RefId Name
---------------------
1 Jack
2 Sam
3 Jane
Games tbl Blocks tbl
GameId GameDate BlockId RefId BlockDate
------------------------- ----------------------
1 8/21/2021 1 2 8/21/2021
2 9/11/2021 2 2 9/11/2021
3 9/18/2021 3 3 8/21/2021
Desired Output
----------------------------------
If Game 1 is selected: Jack
If Game 2 is selected: Jack and Jane
If Game 3 is selected: Jack, Sam and Jane
The only 2 tables that are related are the Officials table and Blocks table, with the RefId. I need to compare the BlockDate of Blocks table to GameDate of Games table. I have tried some sql language and this below is obviously not correct, but I'm looking for a way to accomplish what I want to do:
#GameDate datetime,
Select c.Id, c.Name
From Officials c
Where In c.Id And Blocks.BlockDate <> Games.GameDate)
You can do it with NOT EXISTS:
SELECT o.*
FROM Officials o
WHERE NOT EXISTS (
SELECT 1
FROM Blocks b INNER JOIN Games g
ON g.GameDate = b.BlockDate
WHERE b.RefId = o.RefId AND g.GameId = ?
);
See the demo.

sql join gives cumulative results

I want to join county and county_type tables and get only those county that doesnt have a type =30. From below example id = 1 and 3 should only be the expected output
county
id name zipcode
1 LC 12345
2 WC 98765
3 AC 09876
4 VC 90876
county_type
id type
1 10
1 20
2 10
2 20
2 30
3 10
3 20
4 10
4 20
4 30
output:
id name zipcode
1 LC 12345
3 AC 09876
Tried this:
select *.c from county c, county_type ct
where c.id = ct.id
and ct.id != 30
order by c.id asc;
what i am getting is cumulative:
id name zipcode
1 LC 12345
1 LC 12345
2 WC 98765
2 WC 98765........///
You want not exists:
select c.*
from county c
where not exists (select 1
from county_type ct
where ct.id = c.id and ct.type = 30
);

I want movie name from the given database

Performance table:
PerformanceId SingerId MovieId NumberofSongs
1 1 1 2
2 3 1 4
3 2 2 6
4 4 5 3
5 5 5 3
6 2 6 2
7 4 6 5
8 6 4 6
9 6 3 3
10 4 3 4
Singer table:
SingerId SingerName City DOB Gender
1 A Hyderabad 14-Apr-65 M
2 B Chennai 25-May-84 M
3 C Bangalore 14-Sep-78 F
4 D Hyderabad 17-Jan-70 M
5 E Hyderabad 18-Mar-87 F
6 F Bangalore 23-Aug-75 F
Movie table:
MovieId MovieName ReleaseDate
1 AAA 12-Jan-15
2 BBB 19-Sep-12
3 CCC 23-Jul-10
4 DDD 06-Oct-01
5 EEE 08-Nov-05
6 FFF 18-Apr-99
7 GGG 07-Aug-12
I would need to list the MovieId, MovieName in which both Male and Female singers are performed
(list the movieid, moviename in which male and femail singer ie both singer are performed in one movie)
Hi guys please help me out with this query i tried i am not getting exact query
Here's my query:
select * from movies a inner join performance b
on a.movie_id=b.movie_id where b.singer_id in
(select singer_id from singer where gender = 'F') c inner join
(SELECT SINGER_ID FROM SINGER WHERE gender = 'M') d
on c.singer_id=d.singer_id;
First create a view "MOVIE_ANALYSIS" where you'll have a list of all movies and if they've mixed singers or not:
CREATE VIEW MOVIE_ANALYSIS AS SELECT
M.MOVIEID ,
M.MOVIENAME,
(COUNT(DISTINCT S.GENDER) > 1) AS MIXED
FROM MOVIE M
INNER JOIN PERFORMANCE P ON P.MOVIEID = M.MOVIEID
INNER JOIN SINGER S ON S.SINGERID = P.SINGERID
GROUP BY M.MOVIEID ;
Then you'll get your final result with this query:
SELECT * FROM MOVIE_ANALYSIS WHERE MIXED IS TRUE ;
The reason I used an intermediate view is that in several SQL engines, you cannot use the computed "mixed" attribute directly in the same query with a group by. It'll keep insisting that mixed column is missing.
Validated and test on H2. I did not test on Oracle, as I've no access to it.
What you want here is the INTERSECT statement (using Oracle):
select movieId
from performance a
where exists (select 1
from singer b
where A.singerID = b.singerID
and b.gender = 'F')
intersect
select movieId
from performance a
where exists (select 1
from singer b
where A.singerID = b.singerID
and b.gender = 'M');
Then you just join the movie IDs you get back to the Movie table.
INTERSECT will only bring back IDs that are common to both queries (or however many you use).

SQL Server Adding Count up

I'm working on a query and I'm getting the result as intended but they're not adding up
My Query
SELECT SUBSTRING(h.HotelName, 1, CHARINDEX(' ', h.HotelName)) AS 'HotelName', LEFT(r.RoomNumber, 1) AS Floor, COUNT(*) AS 'Rooms'
FROM HOTEL AS h
JOIN HOTELROOMTYPE AS hr ON h.HotelID = hr.HotelID
JOIN ROOM AS r ON hr.HotelRoomTypeID = r.HotelRoomTypeID
GROUP BY r.RoomNumber, h.HotelName
My Results
HotelName Floor Rooms
------------------------------ ----- -----------
John's 2 1
John's 2 1
John's 3 1
University 1 1
University 1 1
University 2 1
University 2 1
University 2 1
Utah 2 1
Utah 2 1
Utah 2 1
Intended results
HotelName Floor Rooms
------------------------------ ----- -----------
John's 2 2
John's 3 1
University 1 2
University 2 3
Utah 2 3
Basically I want the Rooms for each floor to be added up, any help would be great.
If you want the floor in the output, then group by it:
SELECT SUBSTRING(h.HotelName, 1, CHARINDEX(' ', h.HotelName)) AS HotelName,
LEFT(r.RoomNumber, 1) AS Floor, COUNT(*) AS 'Rooms'
FROM HOTEL h JOIN
HOTELROOMTYPE hr
ON h.HotelID = hr.HotelID JOIN
ROOM r
ON hr.HotelRoomTypeID = r.HotelRoomTypeID
GROUP BY h.HotelName, LEFT(r.RoomNumber, 1);
I presume none of your hotels have more than 9 floors.