SQL GROUP BY 或 JOIN
Posted
技术标签:
【中文标题】SQL GROUP BY 或 JOIN【英文标题】:SQL GROUP BY or JOIN 【发布时间】:2013-03-12 04:30:51 【问题描述】:我正在使用 SQL 2008,但无法使该查询正常工作。我有一张表,里面有航班价格的详细信息。每条路线每天都有很多行,我想返回路线每天的最低价格以及 DateAdded(添加行的日期时间)。我快到了,因为我似乎设法获得了每天最低的退货价格,但我似乎无法获得正确的退货日期。下面的代码似乎可以返回每天的最低价格,但我认为我需要某种连接才能返回 DateAdded?
ALTER PROCEDURE [dbo].[FlightInfoLowestPricePerDay]
(
@AirportFrom varchar(5),
@AirportTo varchar(5)
)
AS
select DATEADD(dd, 0, DATEDIFF(dd, 0, TimeDeparture)) as FlightDate, MIN(Price) as MinPrice
from FlightInfo
where AirportFrom = @AirportFrom and AirportTo = @AirportTo
AND TimeDeparture > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
Group By DATEADD(dd, 0, DATEDIFF(dd, 0, TimeDeparture))
Order by FlightDate ASC
我已经尝试过以下代码之类的东西,但我还没有完全理解连接,所以虽然我确定我错过了一些非常简单的东西,但我已经挣扎了很长时间!
ALTER PROCEDURE [dbo].[FlightInfoLowestPricePerDay]
(
@AirportFrom varchar(5),
@AirportTo varchar(5)
)
AS
select DATEADD(dd, 0, DATEDIFF(dd, 0, fi1.TimeDeparture)) as FlightDate, MIN(fi1.Price) as MinPrice, fi2.DateAdded
from FlightInfo
fi1 join FlightInfo fi2 on fi1.Price = fi2.Price
where fi1.AirportFrom = @AirportFrom and fi1.AirportTo = @AirportTo
AND fi1.TimeDeparture > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
Group By DATEADD(dd, 0, DATEDIFF(dd, 0, fi1.TimeDeparture))
Order by FlightDate ASC
【问题讨论】:
使用没有连接的第一个查询我认为您可以将 DateAdded 放入像MAX(DateAdded)
这样的聚合函数中
【参考方案1】:
在分组方式中添加 fi2.DateAdded
ALTER PROCEDURE [dbo].[FlightInfoLowestPricePerDay]
(
@AirportFrom varchar(5),
@AirportTo varchar(5)
)
AS
select DATEADD(dd, 0, DATEDIFF(dd, 0, fi1.TimeDeparture)) as FlightDate, MIN(fi1.Price) as MinPrice, Cast(Convert(varchar(20),fi2.DateAdded,101) as datetime) DateAdded
from FlightInfo
fi1 join FlightInfo fi2 on fi1.Price = fi2.Price
where fi1.AirportFrom = @AirportFrom and fi1.AirportTo = @AirportTo
AND fi1.TimeDeparture > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
Group By DATEADD(dd, 0, DATEDIFF(dd, 0, fi1.TimeDeparture)),Cast(Convert(varchar(20),fi2.DateAdded,101) as datetime)
Order by FlightDate ASC
【讨论】:
这不起作用,它现在每天带回多行,而不仅仅是 minprice 行。我只需要与 minprice 相关的添加日期 将 fi2.DateAdded 更改为 Cast(Convert(varchar(20),fi2.DateAdded,101) as datetime) 不,现在我得到了这个: FlightDate MinPrice DateAdded 2013-03-24 00:00:00.000 280 2013-02-01 00:00:00.000 2013-03-24 00:00:00.000 280 2013-02-02 00: 00:00.000 2013-03-24 00:00:00.000 280 2013-02-03 00:00:00.000 2013-03-24 00:00:00.000 280 2013-02-04 00:00:00.000 2013-03-24 00:00:00.000 280 2013-02-05 00:00:00.000 2013-03-24 00:00:00.000 280 2013-02-06 00:00:00.000 2013-03-24 00:00:00.000 280 201-3 02-07 00:00:00.000 2013-03-24 00:00:00.000 280 2013-02-08 00:00:00.000 2013-03-24 00:00:00.000 280 2013-02-09 00:00:00.000 2013-03-24 00:00:00.000 280 2013-02-10 00:00:00.000【参考方案2】:好的,我决定简化一下,因为我已经在这方面浪费了太多时间,所以现在我将一个特定的日期传递给查询并多次运行查询以获得我需要的结果:
ALTER PROCEDURE [dbo].[FlightInfoLowestPriceDateAddedForSpecificDate]
(
@AirportFrom varchar(5),
@AirportTo varchar(5),
@Date datetime
)
AS
select top 1 *
from FlightInfo
where AirportFrom = @AirportFrom and AirportTo = @AirportTo
AND DATEADD(dd, 0, DATEDIFF(dd, 0, TimeDeparture)) = DATEADD(dd, 0, DATEDIFF(dd, 0, @Date))
Order by Price asc
【讨论】:
【参考方案3】:您想为此使用窗口功能。一种方法是使用row_number()
:
select flightDate, price
from (select DATEADD(dd, 0, DATEDIFF(dd, 0, TimeDeparture)) as FlightDate, fi.*,
ROW_NUMBER() over (partition by airportFrom, airportTo, DATEADD(dd, 0, DATEDIFF(dd, 0, TimeDeparture)) order by price) as seqnum
from FlightInfo fi
where AirportFrom = @AirportFrom and AirportTo = @AirportTo and
TimeDeparture > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
) fi
where seqnum = 1
如果您使用的是较新版本的 SQL Server,则可以利用 date
数据类型:
select flightDate, price
from (select cast(TimeDeparture as date) as FlightDate, fi.*,
ROW_NUMBER() over (partition by airportFrom, airportTo, cast(TimeDeparture as date) order by price) as seqnum
from FlightInfo fi
where AirportFrom = @AirportFrom and AirportTo = @AirportTo and
TimeDeparture > cast(getdate() as date)
) fi
where seqnum = 1
【讨论】:
【参考方案4】:您可以进行两个子查询(一个获取每天的小价格,第二个获取 DateAdded)
SELECT f1.FlightDate, f1.MinPrice, f2.DateAdded From
(
SELECT
DATEADD(dd, 0, DATEDIFF(dd, 0, fi1.TimeDeparture)) as FlightDate,
MIN(fi1.Price) as MinPrice
FROM FlightInfo fi1
WHERE fi1.AirportFrom = @AirportFrom and fi1.AirportTo = @AirportTo
AND fi1.TimeDeparture > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
Group By
DATEADD(dd, 0, DATEDIFF(dd, 0, fi1.TimeDeparture))
) f1
INNER JOIN
(
SELECT DISTINCT
DATEADD(dd, 0, DATEDIFF(dd, 0, fi2.DateAdded)) AS DateAdded,
Price FROM FlightInfo fi2
WHERE fi2.AirportFrom = @AirportFrom and fi2.AirportTo = @AirportTo
AND fi2.TimeDeparture > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
) f2 ON f2.Price = f1.MinPrice
【讨论】:
以上是关于SQL GROUP BY 或 JOIN的主要内容,如果未能解决你的问题,请参考以下文章
在 SQL 中使用 Group By 和 Aggregate - 获取错误“选择列表中的列无效,因为它不包含在聚合函数或 GROUP BY 中”