加入排除上一场比赛
Posted
技术标签:
【中文标题】加入排除上一场比赛【英文标题】:Join with exclusion of previous match 【发布时间】:2020-09-23 08:32:11 【问题描述】:假设我有一个表格“在比赛中得分的球员”,其结构如下,其中球员 1 在比赛中得分两次(出现两次),球员 5 得分一次:
playerId | odd
1 | 15
2 | 30
1 | 15
而且我有一组我选择的球员 ID,我打赌会在那场比赛中得分。
用例 1
选择的玩家 ID:[1, 5] 在这里,我打赌玩家 1 和 5 将在比赛中得分一次(ids 在数组中出现一次)。由于玩家 id 1 在比赛中实际得分两次,我的赌注仍然部分正确,所以我的得分是 15。
用例 2
选择的玩家 ID:[1, 1, 5] 在这里,我打赌玩家 id 1 将得分两次(在我选择的 id 中出现两次),id 5 将得分一次。 由于玩家 id 1 在比赛中得分两次,我的得分是 15 + 15。
用例 3
选择的球员 ID:[1, 1, 5] 让我们假设球员 1 在比赛中得分一次。 我的赌注是部分正确的。我得到 +15。
用例 4
选择的玩家 ID:[3]。 我打赌 plyaer id 3 得分,事实并非如此,我得到 0 分。
这是一个代码示例,其中我有两个用例,第一个是使用 Mikhail 的解决方案可以正常工作,但不是第二个:
DECLARE matchs STRING;
DECLARE bets STRING;
SET matchs = "['playerId': 550, 'odd': 15, 'scored_at': 1, 'playerId': 550, 'odd': 15, 'scored_at': 2]";
/* Use case 1 -- working */
/*SET playerIdSelected = "[550, 9]";*/
/* Use case 2 -- NOK */
SET playerIdSelected = "[550, 9, 550]";
SELECT
SUM(CAST(first_odd AS INT64)) total
FROM (
SELECT ARRAY_AGG(JSON_EXTRACT_SCALAR(scorers, '$.odd') ORDER BY JSON_EXTRACT_SCALAR(scorers, '$.scored_at') LIMIT 1)[OFFSET(0)] first_odd,
FROM UNNEST(JSON_EXTRACT_ARRAY(matchs, '$.')) AS scorers
WHERE JSON_EXTRACT_SCALAR(scorers, '$.playerId') IN UNNEST(JSON_EXTRACT_ARRAY(playerIdSelected))
GROUP BY JSON_EXTRACT_SCALAR(scorers, '$.playerId')
)
【问题讨论】:
那么,仍然不清楚第二种情况不起作用。您能否以明文形式提供示例输入和预期输出,以便我们更好地帮助您 你是对的。我用预期的输出重写了我的帖子和用例,如果还不清楚,请告诉我:) 【参考方案1】:以下是 BigQuery 标准 SQL
#standardSQL
SELECT SUM(first_odd) total
FROM (
SELECT ARRAY_AGG(odd ORDER BY scored_at LIMIT 1)[OFFSET(0)] first_odd
FROM `project.dataset.scores`
WHERE playerId IN UNNEST([1, 5, 3])
GROUP BY playerId
)
如您所见 - 我正在使用scored_at
列来确定每个玩家的第一个得分。您的数据应该有这样的字段来识别事件的顺序 - 通常这是一个时间戳或类似的东西
如果通过添加 scored_at
字段应用于您的问题中的示例数据 - 输出是
Row total
1 15
以下是更新问题的答案 - 初始问题被明确要求“排除先前的匹配”,因此上述第一个答案中的逻辑是遵循这一点。现在下面的逻辑反映了在呈现的用例中解释的逻辑
#standardSQL
with `project.dataset.scores` as (
select 1 playerId, 15 odd, 1 scored_at union all
select 2, 30, 2 union all
select 1, 15, 3
), selection as (
select [1, 5, 1] playerIds
)
select ifnull(sum(odd), 0) total
from (
select *,
row_number() over(partition by playerId order by scored_at) as score_pos
from `project.dataset.scores`
) join (
select playerId, count(1) max_scores
from selection s, s.playerIds as playerId
group by playerId
) using(playerId)
where score_pos <= max_scores
【讨论】:
米哈伊尔,非常感谢您的回复,并为我的延误感到抱歉。我发生了一次事故,使我无法进行 2 周的开发,但我现在重新站起来,我要回去了!我正在尝试你的代码,我会尽快通知你:) 尝试后,我认为您的解决方案适用于一个用例,但不适用于我选择两次 id 1 的第二个用例,我应该得到 (15 + 15) = 30。我'将编辑并发布一个虚拟代码示例 这肯定对我有用。这也是一种非常聪明的做法。我只需要让它符合我最初的要求,但基础是完美的。谢谢米哈伊尔!以上是关于加入排除上一场比赛的主要内容,如果未能解决你的问题,请参考以下文章