如何组织联合中的行

时间:2016-06-08 08:47:42

标签: sql sql-server tsql

我的结果有点问题,我正在尝试为每个团队创建一个夹具列表,在家里和外面玩。我几乎让它工作但我遇到的问题显示在以下结果中:

enter image description here

我有2支球队在第1周主场和客场比赛,并且相同的两支球队在一周内主场和客场比赛。

当我插入数据并阅读它时,应该显示的是第1周,第4组是在主场比赛18队,然后在第4周进行反向比赛。

换句话说,第2行和第3行不正确,只应显示第1行和第4行。我需要在下面的代码中更改哪些内容才能使其生效?

INSERT INTO dbo.Fixture (WeekNumber, HomeTeamID, AwayTeamID, FixtureDate, LeagueID)
SELECT
    ROW_NUMBER() OVER (PARTITION BY h.teamID ORDER BY h.TeamID, a.TeamID, h.LeagueID) AS WeekNumber,
    h.TeamID,
    a.TeamID,
    DATEADD(day,(ROW_NUMBER() OVER (ORDER BY h.LeagueID)-1)*7,@StartFixtureWeek) AS FixtureWeek, 
    h.LeagueID
FROM dbo.Team h
CROSS JOIN dbo.Team a
WHERE h.TeamID <> a.TeamID
AND h.LeagueID = a.LeagueID
UNION
SELECT
    ROW_NUMBER() OVER (PARTITION BY a.teamID ORDER BY h.TeamID, a.TeamID, h.LeagueID) AS WeekNumber,
    h.TeamID,
    a.TeamID,
    DATEADD(day,(ROW_NUMBER() OVER (ORDER BY a.LeagueID)-1)*7,@StartFixtureWeek) AS FixtureWeek, 
    h.LeagueID
FROM dbo.Team h
CROSS JOIN dbo.Team a
WHERE h.TeamID <> a.TeamID
AND h.LeagueID = a.LeagueID


select * from dbo.Fixture
WHERE (HomeTeamID = 4 AND AwayTeamID = 18) OR (HomeTeamID = 18 AND AwayTeamID = 4)

更新:

以下是所需输出的说明和设计:

WeekNumber  HomeTeamID   AwayTeamID  FixtureWeek  LeagueID
1           1             4          10-06-2016         1
2           1             3          17-06-2016         1
3           1             2          24-06-2016         1
4           4             1          30-06-2016         1
5           3             1          06-07-2016         1
6           2             1          13-07-2016         1
1           2             3          10-06-2016         1
2           2             4          17-06-2016         1
3           3             4          24-06-2016         1
4           3             2          30-06-2016         1
5           4             2          06-07-2016         1
6           4             3          13-07-2016         1
1           5             8          10-06-2016         2
2           5             7          17-06-2016         2
3           5             6          24-06-2016         2
4           8             5          30-06-2016         2
5           7             5          06-07-2016         2
6           6             5          13-07-2016         2
1           6             7          10-06-2016         2
2           6             8          17-06-2016         2
3           7             8          24-06-2016         2
4           7             6          30-06-2016         2
5           8             6          06-07-2016         2
6           8             7          13-07-2016         2

好的,有两个联盟(LeagueID 1和LeagueID 2)

在联赛1中有4支球队(TeamID) - 1,2,3,4 - 他们在主客场比赛中互相比赛,但他们不能在同一周内打两场比赛。

在联赛2中有4支球队(TeamID) - 5,6,7,8 - 他们在主场和客场比赛,但他们不能在同一周内打两场比赛。

两个联赛都在同一天开始,每场比赛增加7天(换言之,每周一次)

输出没有显示它,但是如果每个团队可以在一周内玩他们的主游戏然后在下一周玩游戏,然后玩回家,然后离开等,则更好。但是如果我们可以得到上面的输出显示第一个和然后小心翼翼地命令他们回家然后那就没事了。

1 个答案:

答案 0 :(得分:0)

带有CROSS JOIN

h.TeamID <> a.TeamID会生成所有对,即(1,2)(2,1)。我认为如果我们将它们分开会更容易,因此WHERE过滤器会变为h.TeamID > a.TeamIDh.TeamID < a.TeamID

应为每个联盟分配周数,因此应按LeagueID进行分区。然后是以某种方式对团队进行排序,然后是相反的方向。

在下面的结果中,您可以看到6周的团队模式如何在两个相反的方向重复。

最有可能的是,CROSS JOIN使用不<>的{​​{1}}和UNION中更复杂的表达式,ROW_NUMBER可能会获得相同或相似的结果。

附注:如果您不需要,请不要使用UNION。使用UNION ALL

附注2:如果您在此处使用CROSS JOININNER JOIN,则无关紧要。优化器会生成相同的执行计划。我认为这里的CROSS JOIN更具可读性,更清楚地表明生成笛卡尔积的意图 - 所有对的集合。

示例数据

DECLARE @T TABLE (TeamID int, LeagueID int);

INSERT INTO @T (TeamID, LeagueID) VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 1),
(5, 2),
(6, 2),
(7, 2),
(8, 2);

<强>查询

SELECT
    h.TeamID AS HomeTeamID
    ,a.TeamID AS AwayTeamID
    ,h.LeagueID
    ,ROW_NUMBER() OVER 
        (PARTITION BY h.LeagueID ORDER BY h.TeamID, a.TeamID) AS WeekNumber
    ,1 AS SortOrder
FROM
    @T AS h
    CROSS JOIN @T AS a
WHERE
    h.LeagueID = a.LeagueID
    AND h.TeamID < a.TeamID

UNION ALL

SELECT
    h.TeamID AS HomeTeamID
    ,a.TeamID AS AwayTeamID
    ,h.LeagueID
    ,ROW_NUMBER() OVER 
        (PARTITION BY h.LeagueID ORDER BY a.TeamID DESC, h.TeamID DESC) AS WeekNumber
    ,2 AS SortOrder
FROM
    @T AS h
    CROSS JOIN @T AS a
WHERE
    h.LeagueID = a.LeagueID
    AND h.TeamID > a.TeamID

ORDER BY
    LeagueID
    ,SortOrder
    ,WeekNumber
;

<强>结果

+------------+------------+----------+------------+-----------+
| HomeTeamID | AwayTeamID | LeagueID | WeekNumber | SortOrder |
+------------+------------+----------+------------+-----------+
|          1 |          2 |        1 |          1 |         1 |
|          1 |          3 |        1 |          2 |         1 |
|          1 |          4 |        1 |          3 |         1 |
|          2 |          3 |        1 |          4 |         1 |
|          2 |          4 |        1 |          5 |         1 |
|          3 |          4 |        1 |          6 |         1 |
|          4 |          3 |        1 |          1 |         2 |
|          4 |          2 |        1 |          2 |         2 |
|          3 |          2 |        1 |          3 |         2 |
|          4 |          1 |        1 |          4 |         2 |
|          3 |          1 |        1 |          5 |         2 |
|          2 |          1 |        1 |          6 |         2 |
|          5 |          6 |        2 |          1 |         1 |
|          5 |          7 |        2 |          2 |         1 |
|          5 |          8 |        2 |          3 |         1 |
|          6 |          7 |        2 |          4 |         1 |
|          6 |          8 |        2 |          5 |         1 |
|          7 |          8 |        2 |          6 |         1 |
|          8 |          7 |        2 |          1 |         2 |
|          8 |          6 |        2 |          2 |         2 |
|          7 |          6 |        2 |          3 |         2 |
|          8 |          5 |        2 |          4 |         2 |
|          7 |          5 |        2 |          5 |         2 |
|          6 |          5 |        2 |          6 |         2 |
+------------+------------+----------+------------+-----------+