Complex SQL query for a large record set - sql

I have 3 tables. Lets start by explaining the first one
tblDistance: (airport1, airport2, distance) // airport1 and airport 2 are airport codes
This table contains the distances in miles between all airports of America there are a total of 3745 airports and the distances were calculated using a nested for loop and with each loop the counter was decremented. So for the 1st airport we calculated 3744 distances. For the second we calculated 3743 distances as we have already calculated its distance in the first loop with the first airport. Now lets say the first airport was Animas Air Park(K00C) and the second aiport is Broadus Airport(K00F). The records would appear in tblDistance as
(KOOC, other3744aiports, distance)
For second airport
(K00C, K00F, distance) //This one record has been already calculated in 1st iteration of the loop
(KOOF, other3743aiports, distance)
So except for the 1st airport if we want to find all the distances for a particular airport lets say K00F we need a union query given below.
(SELECT * FROM tblDistances WHERE tblDistances.airport1 = 'K00F')
UNION ALL
(SELECT * FROM tblDistances WHERE tblDistances.airport2 = 'K00F');
I hope I have explained it clearly. Now lets come to the other 2 tables. They are called tblHave and tblNeed
tblHave: (departure, departCode, arrival, arrivalCode, flightDate)
tblNeed: (departure, departCode, arrival, arrivalCode, flightDate)
Departure is the name of the airport from which the flight will depart and the departCode(K00C, K00F) is the code of the airport and same goes for arrival and arrivalCode.
Assume that we have a flight from (departure) San Francisco Intl (KSFO) to (arrival) South Bend Rgnl (KSBN) in the tblNeed. Now comes the real problem we have to find all the flights in the tblHave that are
On the same date as the given flight and
Departure airport is (KSFO) or within 500 miles of San Francisco Intl (KSFO) using union as explined above (lets call it qryDepart) AND
Arrival airport is (KSBN) or within 500 miles of South Bend Rgnl (KSBN) using union as explined above (lets call it qryArrival)
Sample qryArrival
SELECT tblDistances.airport2 as nearBy
FROM tblDistances
WHERE tblDistances.airport1 = 'KSFO' AND (((Abs([tblDistances].[distance]))<=500))
UNION ALL SELECT tblDistances.airport1 as nearBy
FROM tblDistances
WHERE tblDistances.airport2 = 'KSFO' AND (((Abs([tblDistances].[distance]))<=500));
I cannot figure out how can I find this and also the total no.of distance commbinations for all airports is more than 7 million. The records are in Access database. What I have figure is that I find nearby departure airports and nearby arrival airports from tblDistances and then use the IN clause to find the final results
Select * from tblHave where arrivalCode IN (qryArrival) AND departCode IN (qryDepart) AND Date = #dd/mm/yyyy#;
this is not working and the union takes too much time as the no of records is very large.

You don't need to use UNION here. You can do it in one query which should cut your execution time in half at least since you won't be checking every record twice. You can use a nested iif statement to determine which field to use for nearBy, and then change your WHERE to check both fields of the record. Like this:
SELECT
iif(
tblDistances.airport = 'KSFO',
tblDistances.airport2,
iif(tblDistances.airport2 = 'KSFO',
tblDistances.airport1,
null)
) as nearBy
FROM tblDistances
WHERE
(
tblDistances.airport1 = 'KSFO'
OR tblDistances.airport2 = 'KSFO'
)
AND (((Abs([tblDistances].[distance]))<=500))
Which would be much easier to read if you used a CASE statement, but Access doesn't support CASE. The above query does the same thing as:
SELECT
CASE
WHEN tblDistances.airport1 = 'KSFO' then tblDistances.airport2
WHEN tblDistances.airport2 = 'KSFO' then tblDistances.airport1
END as nearBy
FROM tblDistances
WHERE
(
tblDistances.airport1 = 'KSFO'
OR tblDistances.airport2 = 'KSFO'
)
AND (((Abs([tblDistances].[distance]))<=500))

Related

Need a SQL Server query to eliminate the Highlighted Rows ( Returning Routes in Flight)

I have a requirement where I need to eliminate all the rows which have returning flight routes.
I have highlighted the routes in the orange color which depicts this behavior.
For example, row 1 has one route BKI - MYY and row 4 has MYY - BKI. I need a flag (Boolean 1/0) that checks the entire row and sees if it's a returning flight or not.
Note: there are a few scenarios where the flight started at 10:00 PM night today and returned the next day early morning. if it is a consecutive day then we need to eliminate that rows as well.
Any thought on how to solve this?
Gsheet link : Sample Data : https://docs.google.com/spreadsheets/d/1ibrUfOTMEx4i-erDQnIfszdcEvJKU_oFcnMBFcGbvyM/edit?usp=sharing
Definition: Return flight is a two-way journey by air. If a flight is starting from the source and after certain hop/route returns backs to the same source (Departure Station)
std_utc = Departure Time
Sta_utc = Arival Time
with AllFlight as
(
select row_number()over(order by std_utc)rn, aoc,hub,flight ,departure,arrival,std_utc,sta_utc
from TABLENAME01
),
returnFlight as
(
select * from AllFlight s
where exists
(
select * from AllFlight s2
where s2.rn<s.rn and s2.arrival=s.departure and s2.departure=s.arrival
and
(date_diff(EXTRACT(DATE FROM s.sta_utc),EXTRACT(DATE FROM s2.std_utc), DAY))<=1
)
)
select aoc,hub,flight ,departure ,arrival,std_utc ,sta_utc from AllFlight where rn not in (select rn from returnFlight)
This query is kept on running and not giving me the desired output.
Note: I am using Bigquery
I have created a table named S65828793 with your provided data. First I have numbered the rows in ascending sequence of departure time. Then from that I have identified the flights that have been another flight within two consecutive days from opposite direction and marked those as returning flight.
Then at last I have excluded all the returning flight from the total flight list.
with AllFlight as (
select row_number()over(order by departuretime)rn, aoc ,hub ,flight ,departure ,arrival ,DepartureTime ,ArrivalTime from S65828793
),
returnFlight as (select * from AllFlight s
where exists (select * from AllFlight s2 where s2.rn<s.rn and s2.arrival=s.departure and s2.departure=s.arrival and datediff(day,cast(s.ArrivalTime as date),cast(s2.departuretime as date))<=1))
select aoc ,hub ,flight ,departure ,arrival ,DepartureTime ,ArrivalTime from AllFlight where rn not in (select rn from returnFlight)
Result:

I am trying to write a SQL nested query that finds/uses a max value to find the entry just before the max value

I am fairly new to SQL and am trying to write a query that finds the last time a water meter was read so I can see the value. There is a table of properties that have meters and another table of meters that stores the inputs from engineers. Every input is listed as a sequence, a keyword lists the type of input and expression lists their entry. The max sequence will not always be the answer.
What I am looking for is the last time the read the meter for water and then also get the value for electricity from that reading which is stored in the previous entry (sequence). To make it harder engineers input the sequence number and some go by ones (1,2,3) and others go by twos (2,4,6) so the previous entry may be minus one or maybe minus two.
I can write the queries to find the max sequence and another one to find the entry one previous or two previous but cannot figure out how to make it into one query.
to find the max sequence for site 12345, I have:
SELECT MAX(M.SEQUENCE) maxseq
FROM METERS M JOIN PROPERTY P ON M.PROPNUM = P.PROPNUM
WHERE (P.CORP_ID ='12345' AND M.KEYWORD = 'WTR')
I manually search for the entry before to get the electricity entry with the following query.
SELECT P.NAME, P.CORP_ID, M.KEYWORD, M.SEQUENCE, M.EXPRESSION
FROM METERS M JOIN PROPERTY P ON M.PROPNUM = P.PROPNUM
WHERE (P.CORP_ID ='12345')
ORDER BY M.SEQUENCE
I have tried different nested queries but have not been able to write anything that will work.
The data that I am interested in for the meters table looks like:
PROPNUM SEQUENCE KEYWORD EXPRESSION
10a124 95 ELC 9845
10a124 96 WTR 4521
10a124 97 SVC A105
10a124 98 HEALTH GOOD
10a124 99 DAY 150209
10a124 100 HEALTH GOOD
10a124 101 ELC 10283
10a124 102 WTR 4621
I use the property table to find the PROPNUM for the site I am interested as I have the site's ID (CORP_ID) but not its PROPNUM value.
The result I would like to get back would look like below.
NAME WTR_EXPRESSION ELC_EXPRESSION
SMITH 4621 10283
You can inner join the METER table to the PROPERTY table once for each KEYWORD, and specify that the SEQUENCE for 'ELC' (guessing KEYWORD) is less than the 'WTR' SEQUENCE. Since you are on SQL SERVER, we can do this in a CTE and inner join that data set to the METER table to display the EXPRESSION values for each KEYWORD in a single row:
;with wtr_elc as (
select
p.PROPNUM,
p.NAME,
max(w.SEQUENCE) as max_wtr_seq,
max(e.SEQUENCE) as max_elc_seq
from PROPERTY as p
inner join METERS as w
on w.PROPNUM = p.PROPNUM
w.KEYWORD = 'WTR'
inner join METERS as e
on e.PROPNUM = p.PROPNUM
and e.KEYWORD = 'ELC'
and e.SEQUENCE < w.SEQUENCE
where p.CORP_ID ='12345'
group by
p.PROPNUM,
p.NAME)
select
wtr_elc.NAME,
wtr.EXPRESSION as WTR_EXPRESSION,
elc.EXPRESSION as ELC_EXPRESSION
from METERS as wtr
inner join wtr_elc
on wtr_elc.PROPNUM = wtr.PROPNUM
and wtr_elc.max_wtr_seq = wtr.SEQUENCE
inner join METERS elc
on wtr_elc.PROPNUM = elc.PROPNUM
and wtr_elc.max_elc_seq = elc.SEQUENCE
and elc.KEYWORD = 'ELC'
where wtr.KEYWORD = 'WTR'
If you want to do this for more or all PROPERTY records, you can modify the where clause in the CTE.

Complex SQL query assistance

I have a DB that contains informations about buses arriving to/departing from a station. In my application, I need to display all departures from the station that the user selects.
That means that I have to identify each line that passes trough the selected station. I did that with the following query:
SELECT DISTINCT LinePaths.TimetableID
,Lines.LineName AS [Line]
,Timetable.Heading
,LinePaths.Departure
,Regime.Name AS [Regime]
FROM LinePaths
INNER JOIN Timetables ON Timetables.TimetableID = LinePaths.TimetableID
INNER JOIN Lines ON Timetable.LineID = Lines.LineID
INNER JOIN Stations ON LinePaths.Station = Station.StationID
INNER JOIN Regimes ON Timetables.Regime = Regimes.RegimeID
WHERE Station = #Station
The problem is that instead of Timetable.Heading I need to display the name of the final station that the bus is heading to. These are the schema's of the tables I have at my disposal:
Stations - ID, Name
Lines - LineID, LineName
Timetable - TimetableID, LineID, Heading, Regime (Regime defines on which days the bus drives)
LinePaths - ID, TimetableID, SN, Arrival, Departure, StationID (The SN is a serial number that defines the order of stations on a certain paths (the bus will arrive to those stations in that particular order).)
So, instead of the Timetable.Heading I need to have a Stations.Name, and here I come to my problem.
That column has to represent the final station to which the bus is going (for every line), so I have to somehow identify the final station (again for each line that passes trough the selected station). For that I have to use the LinePaths table. Inside that table the data is grouped by TimetableID, so that the entries with the same value for the TimetableID are ordered by the SN value that represents the order in which the bus arrives to the stations (like this: xxxxx, 1111, 3, 8:15, 8:20, 9999) - this means that the bus that drives according to the timetable 1111 will arrive at 8:15 to the station with StationID 9999, leave at 8:20, and that station is the 3rd one on this route (the xxxxx is the ID of the LinePath, and is not important for this query).
So, finally, my question is - how can I, using SQL, get the data in the following schema:
FinalStationName,
Departure(from selected station),
Regime.
The most efficient way would be to have a new table with a TimetableID and the name of the final station, and join this table with the other ones, but if you really need to obtain the value without additional tables, you new to calculate the final station for each timetable. This query obtains the id of each timetable and the name of the last station
SELECT li.TimetableID, s.Name
FROM LinePaths li INNER JOIN
(SELECT TimetableID, max(SN) as SN FROM LinePaths) as aux
ON aux.TimetableID = li.TimetableID AND aux.SN = li.SN
INNER JOIN Stations s
ON s.ID = li.StationID
and you could use it as a subquery and join it to your query via the TimetableID. Not the most efficient thing, but it should work.

sql queries to show the most popular record

I have four tables
Car (car_ registration_no, class, type_code)
Rental_history (rent_date, car_registration_no, rent_location_code, return_location_code)
Type (type_code, make, model)
Location (location_code, branch_name)
I need a query to show the most popular car rented by location.
I need a query to show the total rentals at each location for the previous month?
My code so far is as follows, but I couldn't complete it:
SELECT car.class, car.type_code , type.make, type.model
FROM car , type, rental_history
where rental_history.car_registration_no = car.car_registration_no
and car.type_code = type.type_code
You will need to join the tables and calculate the numbers. Let's start off with an easier query to point you in the right direction.
This will show you how many times a "type_code" car has been rented per location (untested, may contain errors)
SELECT
count(car.car_registration_no) as rental_num,
car.type_code,
rental_history.rent_location_code
FROM car
LEFT JOIN rental_history ON (rental_history.car_registration_no = car.car_registration_no)
GROUP BY car.type_code, rental_history.rent_location_code;
I'm using a left join here because there may be cars that have not been rented and won't have any history. Instead of not showing up, you will have a "0" for number of rentals.
Edit:
For the second query it's actually very straightforward. You need to group by location, filter on date and use COUNT (again, untested):
SELECT
count(rental_history.car_registration_no) as rental_num,
rental_history.rent_location_code
FROM rental_history
WHERE rent_date >= '2012-03-01' AND rent_date < '2012-04-01'
GROUP BY rental_history.rent_location_code;
Join All the table and use count..!

homework - trying to calculate multiple flight stops between two cities?

This is for a database class, using Oracle DB 11g
Tables:
• Flight (flt_no, from_city, to_city, flt_distance,
flt_departs, flt_arrives, flt_price)
• Aircraft (craft_id, craft_name, cruising_range)
• Employee (emp_id, emp_name, emp_salary)
• Certified (emp_id, craft_id)
QUERY: A customer wants to travel from Madison to New York with no more than two changes of flight. List the choice of departures from Madison if the customer wants to arrive at New York by 6pm.
ANY Help is appreciate for this. I really don't even know where to start on this.
EDIT
This is what I've come up with so far. Please let me know if I'm on the right track at least please.
SELECT F.flt_no
FROM Flight F
WHERE F.from_city = 'Madison'
AND F.to_city = 'New York'
AND DATEPART(hh, F.flt_arrives) <= 18
UNION
SELECT F.flt_no
FROM Flight F
WHERE (F.from_city = 'Madison'
AND F.to_city IN (SELECT from_city
FROM Flight F
WHERE F.to_city = 'New York')
)
OR
(F.to_city = 'New York'
AND F.from_city IN (SELECT to_city
FROM Flight F
WHERE F.from_city = 'Madison')
AND DATEPART(hh, F.flt_arrives) <= 18
)
Think of the three cases:
A direct flight.
flight with 1 stop.
a flight with two stops.
Now start stepping through the cases.
For 1. Look for flight that start and stop, you know where and you know when by, right?
For 2. Think about those two flights. Where will they start and end, what will be in common with the two flight. What's the time criteria for each flight?
For 3. Think about those 3 segments and the characteristics of each, including dependencies
Then you finally want the union of all these if all choice are to be shown.
This function: select to_char(DATE,'HH24') may help.
As #Michael Durrant has given the answer I just want to contribute the solution in SQL format.Hope this will help.Please check the Not Equal to sign.
#Direct flight
select f.no
from flights f
where f.arrives=18:00 and (f.from='madison' and f.to='NewYork')
union
# Cases for one connecting flight
select f2.no
from flights f1, flights f2
where f2.arrives=6pm and
f1.from='Madison' and f1.to<>'New York'
and f1.to=f2.from and f2.to='New York'
and f2.depart> f1.arrives
and f2.arrives<'18:00'
union
#Cases involving two connecting flights
select f3.no
from flights f1,flights f2, flights f3
where f1.from='Madison'
and f1.to=f2.from
f1.to<>'New York'
f2.to=f3.from
f2.to<>'New York'
and f3.to='New York'
and f2.depart> f1.arrives
and f3.depart> f2.arrives
and f3.arrives<'18:00'