在同一个表上连接两个不同聚合函数的结果

时间:2011-10-03 07:10:27

标签: sql

我正在尝试合并两个查询,以确定哪一架飞机将在特定时间点(ABCD点)在特定时间(2011-09-19 04:00:00.000)之前。到目前为止,我生成了最后一架飞机到达这一点,以及飞机最后一次离开该点。我目前的想法是,如果它最后一次到达的时间比上一次飞行时更长,那么飞机在指定时间之前仍然在ABCD点。

第一个查询找到飞机最后一次到达某个点的时间:

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

并且第二个查询找到飞机最后一次离开这一点:

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

这两个查询都会生成相应的响应。我意识到为了比较last_departure和last_arrival字段,我需要以某种方式加入表。

我不是一个SQL专家,在过去任何表连接我已经完成了两个完全不同的表之间并没有涉及任何聚合函数所以我的正常子查询和结构都没有工作。

4 个答案:

答案 0 :(得分:6)

最简单的解决方案是

  • 将每个语句转换为子查询
  • 一起加入结果

SQL语句

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

请注意,我使用了full outer join。最有可能inner join就足够了。只有full outer join没有arival_datetime或反之亦然(不太可能发生)时才需要departure_datetime

答案 1 :(得分:3)

尝试这样:

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

答案 2 :(得分:1)

以下解决方案使用标准SQL,并且应该适用于大多数(如果不是全部)主要RDBMS:

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

如果您的特定RDBMS支持CTE和排名函数,您还可以尝试不同的方法:

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

答案 3 :(得分:0)

非常感谢你。我已经工作了10个小时,为期两天。

总之,主查询包装了任意数量的子查询,并通过使用别名命名子查询,您可以将数据从子查询推送到主查询:

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