选择和使用每个分区组的运算符

时间:2016-02-07 14:05:19

标签: sql sql-server sql-server-2014

我有下表存储体育赛事数据。我试图找回哪些事件在返回同一个国家后增加了。

lead

因此,我创建了一个CTE,以查找哪些国家/地区多次举办了一次活动,然后尝试使用eventdate订购的with t as ( select EventId, EventName, Country, Attendance, CONVERT(VARCHAR(11),EventDate,106) as Date from Sports where Country in (select Country from Sports group by Country having count(*)>=2) ), s as ( select *, LEAD(Attendance) over (partition by Country order by cast([Date] as datetime) desc) as PrevAttendance from t ) select EventName, Country, Attendance, Date from s where Attendance > PrevAttendance 函数来查看最近的日期是否有更高的出勤率。< / p>

但是当满足这些条件时,我想显示出勤率较高的行和前一事件的行。我的尝试只显示最近日期的行。

+----------+------------+-----------+-------------+------------+
| EventId  | EventName  | Country   | Attendance  | EventDate  |
+----------+------------+-----------+-------------+------------+
|        1 | Soccer1    | Australia |       12000 | 2015-01-01 |
|        3 | Soccer3    | Australia |       13999 | 2015-03-22 |
|        7 | Tennis1    | America   |       10000 | 2014-01-02 |
|        8 | Tennis2    | America   |       12111 | 2015-10-01 |
+----------+------------+-----------+-------------+------------+

所以我的问题也是,一般来说,你如何在SQL Server 2014中的每个分区/窗口集上执行操作。因为在这个例子中,如果每个国家有更多的事件,我可能还想检查是否最近的出席人数至少比以往任何时候都要大,而不仅仅是之前最紧张的事件。

希望这是有道理的,提前感谢任何帮助。

所以我对这个表的预期结果如下:

{{1}}

2 个答案:

答案 0 :(得分:1)

SET NOCOUNT ON;
CREATE TABLE #sports(
    [EventId] [int] NULL,
    [EventName] [varchar](50) NULL,
    [Country] [varchar](50) NULL,
    [Attendance] [int] NULL,
    [EventDate] [date] NULL
);
INSERT INTO #sports ([EventId], [EventName], [Country], [Attendance], [EventDate]) VALUES (1, N'Soccer1', N'Australia', 12000, CAST(N'2015-01-01' AS Date))
INSERT INTO #sports ([EventId], [EventName], [Country], [Attendance], [EventDate]) VALUES (2, N'Soccer2', N'Mexico', 35999, CAST(N'2016-02-02' AS Date))
INSERT INTO #sports ([EventId], [EventName], [Country], [Attendance], [EventDate]) VALUES (3, N'Soccer3', N'Australia', 13999, CAST(N'2015-03-22' AS Date))
INSERT INTO #sports ([EventId], [EventName], [Country], [Attendance], [EventDate]) VALUES (4, N'Football1', N'Japan', 13555, CAST(N'2003-11-12' AS Date))
INSERT INTO #sports ([EventId], [EventName], [Country], [Attendance], [EventDate]) VALUES (5, N'Football2', N'Japan', 12222, CAST(N'2004-01-01' AS Date))
INSERT INTO #sports ([EventId], [EventName], [Country], [Attendance], [EventDate]) VALUES (6, N'Football3', N'Canada', 13444, CAST(N'2003-02-23' AS Date))
INSERT INTO #sports ([EventId], [EventName], [Country], [Attendance], [EventDate]) VALUES (7, N'Tennis1', N'America', 10000, CAST(N'2014-01-02' AS Date))
INSERT INTO #sports ([EventId], [EventName], [Country], [Attendance], [EventDate]) VALUES (8, N'Tennis2', N'America', 12111, CAST(N'2015-10-01' AS Date))


;WITH cte AS (
    SELECT
        *,
        pat=CASE 
            WHEN LAG(Attendance) OVER (PARTITION BY Country ORDER BY EventId)IS NULL THEN 0 
            WHEN Attendance<LAG(Attendance) OVER (PARTITION BY Country ORDER BY EventId) THEN 0 
            ELSE 1 
        END,
        patid=LAG(EventId) OVER (PARTITION BY Country ORDER BY EventId)
    FROM
        #sports
)
SELECT
    [EventId], [EventName], [Country], [Attendance], [EventDate]
FROM
    cte 
WHERE 
    pat=1
UNION
SELECT
    inn.[EventId], inn.[EventName], inn.[Country], inn.[Attendance], inn.[EventDate]
FROM
    cte AS ou
    INNER JOIN cte AS inn ON
        inn.EventId=ou.patid
WHERE
    ou.pat=1
ORDER BY
    EventId;

DROP TABLE #sports;

结果:

+---------+-----------+-----------+------------+------------+
| EventId | EventName |  Country  | Attendance | EventDate  |
+---------+-----------+-----------+------------+------------+
|       1 | Soccer1   | Australia |      12000 | 2015-01-01 |
|       3 | Soccer3   | Australia |      13999 | 2015-03-22 |
|       7 | Tennis1   | America   |      10000 | 2014-01-02 |
|       8 | Tennis2   | America   |      12111 | 2015-10-01 |
+---------+-----------+-----------+------------+------------+

答案 1 :(得分:0)

使用ROW_NUMBER获取最近的两行。

with
cte as (
   select *,
      lead(Attendance) -- next row
      over (partition by Country
            order by EventDate desc) as PrevAttendance,
      lag(Attendance) -- previous row
      over (partition by Country
            order by EventDate desc) as NextAttendance,
      ROW_NUMBER() 
      over (partition by Country
            order by EventDate desc) as rn

from sports
)
select * 
from cte
     -- only the last two rows
     -- when last row's value is greater than previous row's value 
where (rn = 1 and Attendance > PrevAttendance)
   or (rn = 2 and Attendance < NextAttendance) 

使用累积MIN来查找以前所有行的最小值:

MIN(Attendance) 
over (partition by Country 
      order by EventDate desc
          -- all rows before the current row
      rows between unbounded preceding and 1 preceding)