Sql 联接表并显示具有最近即将到来日期的行

Sql 联接表并显示具有最近即将到来日期的行,sql,sql-server,Sql,Sql Server,如何连续显示最近的即将举行的活动 假设我有两张桌子: EVENTS |id |venueID |eventName |date | |---|-----------|------------|------------| |10 |1 |Volleyball |2018-08-01 | |11 |1 |Concert |2018-08-05 | |12 |1 |Faire |2018-08-07

如何连续显示最近的即将举行的活动

假设我有两张桌子:

EVENTS
|id |venueID    |eventName   |date        |
|---|-----------|------------|------------|
|10 |1          |Volleyball  |2018-08-01  |
|11 |1          |Concert     |2018-08-05  |
|12 |1          |Faire       |2018-08-07  |


VENUES
|id |Name       |
|---|-----------|
|1  |Place1     |
|2  |Place2     |
由于今天是8月3日,即将举行的活动将是“音乐会”,桌子如下所示:

|Venue    |Event   |Date       |
|---------|--------|-----------|
|Place1   |Concert |2018-08-05 |
我当前的代码有一个问题,即如果有多个即将发生的事件,则整行的重复次数与事件的重复次数相同

我希望每一排的场地只显示一次,只有最近的即将举行的活动

此外,即使没有即将举行的活动,我也希望显示与场地的排。相反,它可以说“没有即将到来的事件”

这是我的

SELECT
venues.id,
venues.Name,
events.eventName,
events.date

FROM VENUES

JOIN EVENTS
     ON (venues.id = events.venueID)

WHERE events.date >= '$current_date'

谢谢大家

您将使用
应用

SELECT v.id, v.Name, e.eventName, e.date
FROM VENUES v CROSS APPLY
     (SELECT TOP (1) e.*
      FROM EVENTS e
      WHERE v.id = e.venueID AND e.date >= '$current_date'
     ) e;
select vid, place,eventName,date 
from venues 
left join
  (select evid nevid, min(date) ndate from events where date>getdate()
   group by evid) nxtevents ON nevid=vid
left join events ON evid=vid AND date=ndate

如果您想包括没有即将举行的活动的场馆,您可以使用
外部应用
,而不是
交叉应用
,您可以使用
应用

select v.Venue, coalesce(e.Event, 'No Upcoming Events') Event, e.Date 
from VENUES v outer apply
     ( select top (1) e.*
       from event e
       where e.venueID = v.id and
             e.date >= '$current_date'
       order by e.date
     ) e;

这里有一个替代使用
APPLY
(这可能是更好的方法)的方法。将此查询计划与使用
OUTER APPLY
的答案进行比较后,我不得不说这是一种较差的方法。可能有一些很好的理由使用窗口函数——这可能是一个更复杂的场景

它使用一个窗口函数,通过排序条件(在本例中为日期)获取行号。结果将加入场馆列表,只返回1行(日期最早的一行)。如果两个活动的地点和日期相同,则只有一个活动的行号为1。不能在APPLY中使用窗口函数,因此需要使用内部查询

SELECT v.Name Venue
   , COALESCE(eRanked.eventName, 'No Events') Event
   , eRanked.Date
FROM Venues v
LEFT JOIN (
    SELECT e.VenueId, e.eventName, e.date
       , ROW_NUMBER() OVER (PARTITION BY e.VenueId ORDER BY e.Date) rowId
    FROM Events e
    WHERE e.date > '$curent_date'
) eRanked ON eRanked.VenueId = v.id AND eRanked.RowId = 1
这里有一个很好的老式解决方案,它可以在没有交叉应用的情况下工作:

SELECT v.id, v.Name, e.eventName, e.date
FROM VENUES v CROSS APPLY
     (SELECT TOP (1) e.*
      FROM EVENTS e
      WHERE v.id = e.venueID AND e.date >= '$current_date'
     ) e;
select vid, place,eventName,date 
from venues 
left join
  (select evid nevid, min(date) ndate from events where date>getdate()
   group by evid) nxtevents ON nevid=vid
left join events ON evid=vid AND date=ndate
它使用两个
左连接
,并依赖于同一场地内同一天不会有两个活动的条件


请看这里的演示:

Hey@Gordon,似乎您忘记在子查询中放置
top(1)
。目前,查询将列出给定场馆列表的所有未来活动,请参见此处@cars10m。抢手货