我需要一些帮助来编写一个相当复杂的Oracle SQL查询。
我有一个表格,其中包含两个团队之间玩的游戏列表,其中包含以下列:
Game Date
(约会)Home Team
(varchar2(26)),Opposition Team
(varchar2(26)),Score Difference
(数字(38))我还创建了一个索引,它只是每个游戏(表格中的每一行)的唯一ID,称为索引'。
比赛中约有30支球队,已经参加了超过5000场比赛。
对于每场比赛(每排一场),我希望能够确定第三支球队(称为共享对手),这是由主队和反对队共享的最近(以天为单位)对手。然后我想计算这些历史比赛的两场比赛(主队和共同对手和反对队与共有对手)的得分差异与当前比赛的详细信息(主队和反对队之间)
到目前为止我的尝试看起来像这样
SELECT
A.GAME_DATE,
A.GAME_NUMBER,
A.INDEXING,
A.HOME_TEAM,
A.OPP_TEAM,
B.OPP_TEAM AS SHARED_OPP,
B.SCORE_DIFF AS OPP_SCORE_DIFF,
C.SCORE_DIFF AS HOME_SCORE_DIFF,
MIN((A.GAME_DATE - B.GAME_DATE)+ (A.GAME_DATE - C.GAME_DATE) + ABS(B.GAME_DATE - C.GAME_DATE)) AS TOTAL_DATE_DIFF
FROM
TEAM_SUMMARY_1 A
LEFT JOIN TEAM_SUMMARY_1 B ON A.OPP_TEAM = B.HOME_TEAM
LEFT JOIN TEAM_SUMMARY_1 C ON A.HOME_TEAM = C.HOME_TEAM
WHERE
B.OPP_TEAM <> A.HOME_TEAM AND
A.OPP_TEAM <> C.OPP_TEAM AND
B.OPP_TEAM = C.OPP_TEAM AND
ABS(B.GAME_DATE - C.GAME_DATE) < 5 AND
A.GAME_DATE - B.GAME_DATE < 20 AND
A.GAME_DATE - B.GAME_DATE > 0 AND
A.GAME_DATE - C.GAME_DATE < 20 AND
A.GAME_DATE - C.GAME_DATE > 0
GROUP BY
A.GAME_DATE,
A.GAME_NUMBER,
A.INDEXING,
A.HOME_TEAM,
A.OPP_TEAM,
B.OPP_TEAM,
B.SCORE_DIFF,
C.SCORE_DIFF
ORDER BY
A.GAME_DATE,
A.HOME_TEAM,
A.OPP_TEAM
此代码确实以某种方式返回我之后的内容,但应用于总日期差异的MIN不起作用。
如果我必须分多步执行此操作,我不介意,但此刻我似乎无法将这个过程概念化。任何帮助,将不胜感激。
答案 0 :(得分:0)
看看这个并将相同的想法应用到你的表结构中。
使用的表格,分数可以是正数或负数,或者是0表示平局。
CREATE TABLE dbo.Game
(
PlayDate DATETIME,
HomeTeam INT,
OpposingTeam INT,
Score INT
)
使用查询
WITH GAME AS
(
SELECT ROW_NUMBER() OVER (ORDER BY G1.PlayDate) I, * FROM dbo.Games G1
)
, SHARED AS
(
SELECT
G.I,
G.HomeTeam,
G.OpposingTeam,
H.HomeTeam AS H,
H.OpposingTeam AS H2,
H.I AS HI,
ROW_NUMBER() OVER (PARTITION BY G.I ORDER BY H.I DESC) AS A
FROM GAME G
LEFT JOIN GAME H ON
(G.OpposingTeam = H.OpposingTeam OR G.OpposingTeam = H.HomeTeam)
AND G.HomeTeam <> H.HomeTeam
AND G.HomeTeam <> H.OpposingTeam
WHERE G.I > H.I
)
SELECT G.*, H.HI
FROM GAME G
LEFT JOIN SHARED H ON G.I = H.I
WHERE A = 1 OR A IS NULL
ORDER BY G.I
基本G.I
id是任何一款游戏。 H.HI
是与共享apponent匹配的游戏。你可以从SHARED
CTE获得你想要的任何领域,如共享游戏的得分,如果共享对手在主场或对方球队等等。其中一些可以稍微成一点但它应该有效。
没有共享对手的游戏出现H
为空
测试数据
INSERT [dbo].[Games] ([PlayDate], [HomeTeam], [OpposingTeam], [Score]) VALUES (CAST(N'2015-01-01 00:00:00.000' AS DateTime), 1, 2, 5)
INSERT [dbo].[Games] ([PlayDate], [HomeTeam], [OpposingTeam], [Score]) VALUES (CAST(N'2015-01-04 00:00:00.000' AS DateTime), 1, 2, 10)
INSERT [dbo].[Games] ([PlayDate], [HomeTeam], [OpposingTeam], [Score]) VALUES (CAST(N'2015-01-10 00:00:00.000' AS DateTime), 1, 2, -3)
INSERT [dbo].[Games] ([PlayDate], [HomeTeam], [OpposingTeam], [Score]) VALUES (CAST(N'2015-01-07 00:00:00.000' AS DateTime), 3, 2, -5)
INSERT [dbo].[Games] ([PlayDate], [HomeTeam], [OpposingTeam], [Score]) VALUES (CAST(N'2015-01-13 00:00:00.000' AS DateTime), 2, 3, -8)
INSERT [dbo].[Games] ([PlayDate], [HomeTeam], [OpposingTeam], [Score]) VALUES (CAST(N'2015-01-04 00:00:00.000' AS DateTime), 2, 1, -8)
INSERT [dbo].[Games] ([PlayDate], [HomeTeam], [OpposingTeam], [Score]) VALUES (CAST(N'2015-01-15 00:00:00.000' AS DateTime), 3, 1, 4)
INSERT [dbo].[Games] ([PlayDate], [HomeTeam], [OpposingTeam], [Score]) VALUES (CAST(N'2015-01-20 00:00:00.000' AS DateTime), 3, 2, 9)
INSERT [dbo].[Games] ([PlayDate], [HomeTeam], [OpposingTeam], [Score]) VALUES (CAST(N'2015-01-24 00:00:00.000' AS DateTime), 1, 3, -15)
答案 1 :(得分:0)
日期逻辑略有不同,但避免了日期的减法:
-- CTE to exchange home and guest teams.
WITH dup AS (
SELECT team_home AS one
, team_guest AS two
, match_date AS match_date
FROM matches
UNION ALL
SELECT team_guest AS one
, team_home AS two
, match_date AS match_date
FROM matches
)
SELECT m0.*
, p1.two AS onetwo, p1.match_date AS onedate
, p2.two AS twotwo, p2.match_date AS twodate
FROM matches m0
-- all other previous matches for home player
JOIN dup p1 ON p1.one = m0.team_home AND p1.two <> m0.team_guest AND p1.match_date < m0.match_date
-- all other previous matches for guest player
JOIN dup p2 ON p2.one = m0.team_guest AND p2.two <> m0.team_home AND p2.match_date < m0.match_date AND p1.two = p2.two
WHERE 1=1
-- suppres older other matches, retaining only the most recent one.
AND NOT EXISTS ( SELECT 1
FROM dup px
JOIN dup py ON py.two = px.two
WHERE px.one = p1.one AND py.one = p2.one
AND px.match_date < m0.match_date AND (px.match_date > p1.match_date OR px.match_date > p2.match_date)
AND py.match_date < m0.match_date AND (py.match_date > p2.match_date OR py.match_date > p1.match_date)
)
ORDER BY
m0.team_home
, m0.match_date
, p1.match_date DESC, p2.match_date DESC
;