SQL:递归搜索每一行

时间:2013-07-22 16:51:27

标签: sql-server tsql sql-server-2012

我甚至不确定这是否可以仅使用SQL,但这里有......

我在一张桌子上有一份足球比赛结果列表,每一行都是一场比赛,包含来自该比赛的所有数据,如主场(球队),主场球场,客场球队,客队(球队),我想在每场比赛中循环,获得主队,检查他们的最后6场比赛,并仅显示指定球队在过去6场比赛的50%或更多中进球2球或以上的比赛。

到目前为止,我有这个,我只是不知道如何将它拼接在一起......

创建所有游戏的列表,仅返回主队:

SELECT *
FROM [FDATA].[dbo].[Goals]
ORDER BY Date

获得该团队的最后6场比赛:(我想对上述查询的每一行进行以下查询)

SELECT TOP 6 *
FROM [FDATA].[dbo].[Goals]
WHERE Home = '[Home] from first query'  AND Date <= '[Date] from first query'  
ORDER BY Date DESC

然后检查球队在返回的6场比赛的&gt; = 50%中是否获得2个或更多目标,如果为真,则输出第一个查询中的行。

所以基本上对于数据库中的每一行,我想找到该行(游戏)中主队的最后6场比赛,看看他们是否在这些比赛的50%或更多中打进2球或更多球,如果是的话,输出原始行,如果没有,则省略结果中的行。

有可能吗?

3 个答案:

答案 0 :(得分:0)

如果您使用的是SQL Server 2005及以上版本:

WITH RankedGoals AS (
   SELECT
      *,
      Sequence = Row_Number() OVER (PARTITION BY G.Home ORDER BY G.Date DESC)
   FROM FDATA.dbo.Goals G
)
SELECT
   G.*
FROM
   RankedGoals G
WHERE
   EXISTS (
      SELECT
         *
      FROM
         RankedGoals S
      WHERE
         G.Home = S.Home
         AND S.Sequence BETWEEN G.Sequence AND G.Sequence + 5
      HAVING
         Sum(CASE WHEN S.Goals >=2 THEN 1 ELSE 0 END) >= 3
         AND Count(*) = 6
   )
;

可以修改查询,以便EXISTS部分使用TOP 6代替日期搜索,这可能会更好,因为它不需要执行窗口功能。但我不确定Date列是否保证唯一。如果是这样,很容易:

SELECT
   G.*
FROM
   FDATA.dbo.Goals G
WHERE
   EXISTS (
      SELECT
         *
      FROM
         (
            SELECT TOP 6 *
            FROM
               FDATA.dbo.Goals S
            WHERE
               G.Home = S.Home
               AND S.Date <= G.Date
            ORDER BY
               S.Date
          ) S
      HAVING
         Sum(CASE WHEN S.Goals >=2 THEN 1 ELSE 0 END) >= 3
         AND Count(*) = 6
   )
;

我强烈建议您在HomeDate列上添加索引...

答案 1 :(得分:0)

SELECT *, NULL as 50percent2ormore
FROM [FDATA].[dbo].[Goals]
INTO #tempgames
ORDER BY Date

Update #tempgames
SET 50percent2ormore = 'Yes'
FROM ( 
SELECT TOP 6 *, count('games with 2 or more goals') as count
FROM #tempgames
WHERE Home = #tempgames.home  
AND Date <= #tempgames.date
ORDER BY Date DESC 
) tmp
WHERE tmp.count >= 3

SELECT * FROM #tempgames WHERE 50percent2ormore = 'Yes'

这可能是一个开始的地方......

答案 2 :(得分:0)

假设SQL Server 2012.未经测试,但我认为这应该有效:

WITH Last6 as (
  SELECT 
    Home, HomeGoals, 
    ROW_NUMBER() OVER (PARTITION BY Home ORDER BY Goals.Date DESC) GameNumber
  FROM Goals
),
Medians as (
  SELECT 
    Home, 
    PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY HomeGoals) OVER (PARTITION BY Home) GoalMedian
  FROM Last6
  WHERE GameNumber <= 6
)    
SELECT *
FROM Goals G
WHERE EXISTS (SELECT NULL FROM Medians WHERE G.Home = Medians.Home AND GoalMedian >= 2)