SQL query tutorials - sql

Given the following tables (i wrote it in this manner to keep things neater)
airline (name, telephone, designator)
flight (name, number, departure, arrival, origin, destination)
airport (name, country, designator)
I would like to print the pairs of names of competing airline. Airlines with the same route or having the same origin and destination. Removing the symmetry from the result as an airline does not compete with itself. Would this work
SELECT a1.name, a2.name
FROM airline a1, airline a2, flight f1, flight f2
WHERE
a1.name <> a2.name
AND a1.name = f1.name
AND a2.name = f2.name
AND f1.origin = f2.origin
AND f1.destination = f2.destination
GROUP BY
a1.name, a2.name;
Then, print the names of the airlines that have flights to all listed airports in thailand.
SELECT DISTINCT a.name
FROM airline a, flight f
WHERE f.destination = ALL(SELECT a.name
FROM airport a
WHERE a.country = 'Thailand');

The first query seem fine, but the second won't work as using ALL in the way you do states that the destination must be equal to all the airport names returned from the subquery which it obviously can't be.
A solution is to write the query on the form show the name of all airlines for which there are no Thai airports that are not in the list of destinations that the airline traffics:
SELECT a.name
FROM airline a
JOIN flight f ON a.name = f.name
WHERE NOT EXISTS (
SELECT name
FROM airport
WHERE country = 'Thailand'
AND name NOT IN (
SELECT destination
FROM flight
WHERE f.name = name
)
)
GROUP BY a.name;

Related

Return record with no permutation duplicate using SQL

I was doing an exercise in SQL: list pairs of hacker both won defcon competition were born after 1990. Only list each pair once.
That is, your query should not return both (zix, wix) and (wix, zix).
I have 3 tables
hackers (name, country, birthday)
winners (hacker, year)
white_paper (title, hacker, year)
Hacker references hackers.name in both tables --> winners and white_paper
How can I return names of hacker each pair with no permutation?
My failed attempt:
select
name, hacker
from
hackers
join
winners on hacker = hackers.name
where
name != hacker
group by
country ;
try this should work
select A1.name as name1, A2.name as name2
from hackers A1, hackers A2, winners
and winners.hacker = A1.name
and winners.hacker = A2.name
where A1.birthday > 1990
and A2.birthday > 1990
and A1.name > A2.name /* this code is the one who help to avoid duplicate
pair */

How can I write SQL Query?

I need a request that displays the name and surname of the clients with the smallest credit limit - among married women who do not live in Japan, Brazil or Italy.
Diagram:
This will Give all the people not in 'Japan', 'Brazil' or 'Italy') ,
Select C.Cust_first_name,C.Cust_Last_name from Customers C
Inner Join Countries C1
on C.Country_Id=C1.Country_Id
Where C1.Country_Name Not in('Japan', 'Brazil' or 'Italy')
and
C.Cust_Credit_Limit=(Select Min(Cust_Credit_Limit) From from Customers C)
If we Convert The Question to Code that will be the above code,
The Script would return the name and last name of person not in ('Japan', 'Brazil' or 'Italy') And has the lowest salary In the entire customer Base.
select top 1 * from Customers C
Inner Join
(
select MIn(cust_credit_limit) from Customers C1
Inner Join Countries CT on C1.Country_id = C1.Country_id
where CT.Country_Name Not in ('Japan', 'Brazil','Italy')
)
C2 on C2.cust_credit_limit = C.cust_credit_limit

SQL Query structure example for recursive lookup

I'm struggling a bit with this query. Perhaps someone can give me a hint?
My setup consists of 3 tables (Actors, Movies, and Relations). What I want to do is:
Find all actors whose name starts with an A that play in any movie alongside Person1.
That's how far i got:
SELECT Name
FROM Actors a, Movies m, Relations r
WHERE a.Name='A%'
AND Person1.keyPerson = m.KeyPerson
AND m.KeyMovies ....
An example on how to continue would be nice!
UPADATE - tables look like this:
Actors (actorsID, name)
Movies (moviesID, title)
Relations (actorsID, moviesID)
There are several ways you can do this - one method you can do is via an IN statement, pulling the movies Person1 has been in, and checking the A% person's movies.
Select Distinct A.Name
From Actors A
Join Relations R On R.ActorId = A.ActorId
Where A.Name Like 'A%'
And R.MovieId In
(
Select R2.MovieId
From Actors A2
Join Relations R2 On R2.ActorId = A2.ActorId
Where A2.Name = 'Person1'
)
Another method is via an EXISTS statement, looking for any movies that Person1 has been in that A% has also been in:
Select A.Name
From Actors A
Join Relations R On R.ActorId = A.ActorId
Where A.Name Like 'A%'
And Exists
(
Select *
From Movies M2
Join Relations R2 On R2.MovieId = M2.MovieId
Join Actors A2 On R2.ActorId = R2.ActorId
Where A2.Name = 'Person1'
And M2.MovieId = R.MovieId
)
A solution without subquery:
SELECT DISTINCT a.Name
FROM Actors a
INNER JOIN Relations r
ON r.actorsID = a.actorsID
INNER JOIN Relations r2
ON r.moviesID = r2.moviesID
INNER JOIN Actors a2
ON a2.actorsID = r2.actorsID
AND a2.Name = 'Person1'
WHERE a.Name LIKE 'A%'

battles, ships sql query

Here is a schema about battleships and the battles they fought in:
Ships(name, yearLaunched, country, numGuns, gunSize, displacement)
Battles(ship, battleName, result)
A typical Ships tuple would be:
('New Jersey', 1943, 'USA', 9, 16, 46000)
which means that the battleship New Jersey was launched in 1943; it belonged to the USA, carried 9 guns of size 16-inch (bore, or inside diameter of the barrel), and weighted (displaced, in nautical terms) 46,000 tons. A typical tuple for Battles is:
('Hood', 'North Atlantic', 'sunk')
That is, H.M.S. Hood was sunk in the battle of the North Atlantic. The other possible results are 'ok' and 'damaged'
Question: List all the pairs of countries that fought each other in battles. List each pair only once, and list them with the country that comes first in alphabetical order first
Answer: I wrote this:
SELECT
a.country, b.country
FROM
ships a, ships b, battles b1, battles b2
WHERE
name = ship
and b1.battleName = b2.battleName
and a.country > b.country
But it says ambiguous column name. How do I resolve it? Thanks in advance
Well, name = ship is the problem. name could be from a or b, and ship from b1 or b2
you could do something like that :
select distinct s1.country, s2.country
from ships s1
inner join Battles b1 on b.ship = s1.name
inner join Battles b2 on b2.ship <> s1.name and b2.battleName = b1.battleName
inner join ships s2 on s2.name = b2.ship and s2.country < s1.country
Could you try a nested query getting a table of winners and losers and then joining them on the battle name?
SELECT
WINNER.country as Country1
,LOSER.country as Country2
FROM
(
SELECT DISTINCT country, battleName
FROM Battles
INNER JOIN Ships ON Battles.ship = Ships.name
WHERE Battles.Result = 1
) AS WINNER
INNER JOIN
(
SELECT DISTINCT country, battleName
FROM Battles
INNER JOIN Ships ON Battles.ship = Ships.name
WHERE Battles.Result = 0
) AS LOSER
ON WINNER.battlename = LOSER.battlename
ORDER BY WINNER.country
try this, i think it's concise:
SELECT DISTINCT s1.country, s2.country
FROM ships s1, ships s2, battles b1, battles b2 -- i just list all tables here but you can use the left join etc.
WHERE s1.name=b1.ship AND s2.name=b2.ship AND b1.battleName=b2.battleName -- for the tables to join each other
AND s1.country < s2.country --key condition
ORDER BY s1.country ASC

Trying to find all the cities that there is not a direct flight to from a city (PostgreSQL)

I'm trying to write a query that determines which cities I can't fly to directly from a city, say London. Given the schema:
cities:
| c_id | city_name |
flights:
| f_id | departure_city_id | destination_city_id |
currently my query returns the opposite, i.e. it returns the cities for which there is a direct flight from London
SELECT c2.city_name as "City"
FROM flights AS f
JOIN cities AS c2 ON f.destination_city_id != c2.c_id
JOIN cities AS c ON c.c_id = c.c_id
WHERE c.city_name = 'London'
AND c.c_id != c2.c_id
AND f.departure_city_id = c.c_id;
I would have thought it would be easy to change it to get what I want.
I thought changing the third line to
JOIN cities AS c2 ON f.destination_city_id = c2.c_id
Would have done the trick but it didn't. Any help?
cities I can't fly to directly from a city, say London.
Meaning one can fly there, just not directly from London. So JOIN (not LEFT JOIN) city to flight via destination_city_id:
SELECT DISTINCT c.city_name
FROM cities c
JOIN flights f ON f.destination_city_id = c.c_id
JOIN cities c2 ON c2.c_id = f.departure_city_id
WHERE c2.city_name <> 'London';
Then I only have to exclude flights originating from London, apply DISTINCT to get unique city names and we are done.
A more sophisticated interpretation of this question would be:
"Cities you can fly to from London, just not directly"
But since this looks like basic homework I don't assume they'd expect a recursive query from you.
Try something like:
SELECT *
FROM cities c
WHERE c.c_id NOT IN
(SELECT f.destination_city_id
FROM flights f
JOIN cities c2 ON f.departure_city_id = c.c_id
WHERE c2.city_name = 'London')