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 中”

SQL中的group by语句和order by语句怎么用?最好能有个例子

SQL GROUP BY 或 JOIN

group by having用法举例

sql语句中的group by啥意思

sql语句中的group by啥意思