Reputation: 2967
I'm trying to combine two queries in order to determine which aircraft will be at a particular point (point ABCD) just before a particular time (2011-09-19 04:00:00.000). So far, I generate the last time an aircraft arrived at this point, and the last time an aircraft departed the point. My current idea is that if the last time it arrived is greater then the last time it departed the aircraft is still at point ABCD just before the specified time.
The first query finds the last time an aircraft arrived at a certain point:
select aircraft_id, MAX(arrival_datetime) as last_arrival
from flight_schedule
where arrival_datetime < '2011-09-19 04:00:00.000' and arrival_point='ABCD'
group by aircraft_id
and the second query finds the last time an aircraft has left this point:
select aircraft_id, MAX(departure_datetime) as last_departure
from flight_schedule
where departure_datetime < '2011-09-19 04:00:00.000' and departure_point='ABCD'
group by aircraft_id
Both of these queries generate the appropriate responses. I realise that in order to compare the last_departure to the last_arrival fields I need to join the tables somehow.
I'm not an SQL whiz, and in the past any table joins I've done have been between two completely different tables and haven't involved any aggregate functions so my normal subqueries and structure hasn't worked.
Upvotes: 8
Views: 15402
Reputation: 1
Thank you so much. I have worked 10 hours spanning two days to get this to work.
In summary, a primary query wraps around any number of sub queries and by naming the sub queries with aliases, you can push data from the sub queries to the main query:
SELECT N.Name_CO_ID, N.Name_Company, N.District_Count, D.DistrictName, D.District_Response
FROM (
SELECT Name_CO_ID, Name_Company, COUNT(dbo.SV_Name.Name_CO_ID) AS 'District_Count'
FROM SV_Name
JOIN dbo.SV_Activity ON dbo.SV_Name.Name_ID = dbo.SV_Activity.Activity_ID
JOIN dbo.SV_Product ON dbo.SV_Activity.Activity_PRODUCT_CODE = dbo.SV_Product.Product_PRODUCT_CODE
AND (dbo.SV_Activity.Activity_ACTIVITY_TYPE = 'COMMITTEE')
AND (dbo.SV_Product.Product_GROUP_3 = 'DIST')
AND (dbo.SV_Activity.Activity_THRU_DATE > GETDATE())
AND (dbo.SV_Name.Name_CO_MEMBER_TYPE = 'LSD')
GROUP BY Name_CO_ID, Name_Company) N
FULL OUTER JOIN (SELECT DistrictName, COUNT(DistrictName)AS 'District_Response'
FROM ODS_Landing
WHERE (StartDate > @StartDate1) AND (StartDate < @StartDate2)
GROUP BY DistrictName) D ON N.Name_COMPANY = D.DistrictName
WHERE District_Response > 0
ORDER BY Name_Company
Upvotes: 0
Reputation: 58431
select la.aircraft_id, la.last_arrival, ld.last_departure
from (
select aircraft_id, MAX(arrival_datetime) as last_arrival
from flight_schedule
where arrival_datetime < '2011-09-19 04:00:00.000' and arrival_point='ABCD'
group by aircraft_id
) la
full outer join (
select aircraft_id, MAX(departure_datetime) as last_departure
from flight_schedule
where departure_datetime < '2011-09-19 04:00:00.000' and departure_point='ABCD'
group by aircraft_id
) ld on ld.aircraft_id = la.aircraft_id
Note that I've used a full outer join
. Most likely an inner join
would suffice. The full outer join
is only needed if there's ever an arival_datetime
without a departure_datetime
or vice versa (wich is unlikely to happen).
Upvotes: 8
Reputation: 77657
The following solution uses standard SQL and should work in most, if not all, the major RDBMSes:
SELECT
aircraft_id,
CASE
WHEN MAX(CASE arrival_point WHEN 'ABCD' THEN arrival_datetime END) >
MAX(CASE departure_point WHEN 'ABCD' THEN departure_datetime END)
THEN 'At the point'
ELSE 'Somwhere else'
END AS is_located
FROM flight_schedule
WHERE arrival_datetime < '2011-09-19 04:00:00.000' AND arrival_point = 'ABCD'
OR departure_datetime < '2011-09-19 04:00:00.000' AND departure_point = 'ABCD'
GROUP BY
aircraft_id
If your particular RDBMS supports CTEs and ranking functions, you could also try a different approach:
WITH events AS (
SELECT
aircraft_id,
arrival_datetime AS event_datetime,
'At the point' AS is_located
FROM flight_schedule
WHERE arrival_datetime < '2011-09-19 04:00:00.000'
AND arrival_point = 'ABCD'
UNION ALL
SELECT
aircraft_id,
departure_datetime AS event_datetime,
'Somewhere else' AS is_located
FROM flight_schedule
WHERE departure_datetime < '2011-09-19 04:00:00.000'
AND departure_point = 'ABCD'
),
ranked AS (
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY aircraft_id
ORDER BY event_datetime DESC
) AS event_rank
FROM events
)
SELECT
aircraft_id,
is_located
FROM ranked
WHERE event_rank = 1
Upvotes: 1
Reputation: 6543
Try like this way :
select dpt.aircraft_id, last_arrival, last_departure
from
(
select aircraft_id, MAX(arrival_datetime) as last_arrival
from flight_schedule
where arrival_datetime < '2011-09-19 04:00:00.000' and arrival_point='ABCD'
group by aircraft_id
) dpt
inner join
(
select aircraft_id, MAX(departure_datetime) as last_departure
from flight_schedule
where departure_datetime < '2011-09-19 04:00:00.000' and departure_point='ABCD'
group by aircraft_id
) arr on dpt.aircraft_id = arr.aircraft_id
Upvotes: 3