加入排除上一场比赛

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。我'将编辑并发布一个虚拟代码示例 这肯定对我有用。这也是一种非常聪明的做法。我只需要让它符合我最初的要求,但基础是完美的。谢谢米哈伊尔!

以上是关于加入排除上一场比赛的主要内容,如果未能解决你的问题,请参考以下文章

Mysql加入多个表排除一些记录

通过设置白名单排除特定搜索引擎违法

Git排除不需要加入文档库的文件

idea 版本控制排除 指定的目录。

流分析查询以排除记录

矢量旋度的散度恒为零