【问题标题】:90-ball bingo - shortest path to winner-ticket90 球宾果游戏 - 获得获胜者门票的最短路径
【发布时间】:2016-10-07 20:55:19
【问题描述】:

对于一个 90 球宾果游戏引擎,我知道所有彩票的外观,我需要根据给定游戏的调用数字来计算获得获胜者彩票的最短路径。

对于每场比赛,我们预计会产生大约 1000 张门票,每场比赛将有三场比赛:“1 行”、“2 行”(显然是一张票)和“全票”。

路径定义为我需要拨打的号码才能获得获胜者门票 - 对于给定的比赛。

表格布局非常简单:

A ticket belongs to a game - it has three rows
A ticket row belongs to a ticket - it has 5 fields
A ticket row field belongs to a ticket row - it has one content field

被叫号码也会在每场比赛中注册。

门票: ID game_id

ticket_row: ID 票号

ticket_row_field: ID ticket_row_id 内容

被叫号码: game_id 被叫号码

所有字段都是整数类型。

我发现很容易获得“1 行”和“全票”比赛的最短路径,我可以分别按ticket_row_id 和ticket_id 分组。

这是我在 1 排比赛中的做法:

select 
    r.ticket_id, 
    count(content) path_distance, 
    group_concat(content order by content) path
from 
    ticket t
    inner join ticket_row r
        on r.ticket_id = t.id
    inner join ticket_row_field f
        on f.ticket_row_id = r.id
    left join called_number n
        on n.game_id = t.game_id
        and n.called_number = f.content
where
    n.called_number is null
group by 
    ticket_row_id
having 
    path_distance < 4
order by 
    path_distance;

我的问题是:如何使用 MySQL(不支持窗口函数)找到“同一张票上 2 行”比赛的最短路径?

用更专业的术语来描述它:对于每张工单,我想找到与 called_number 不匹配的字段内容计数的总和,但仅适用于缺少字段最少的两行。应订购门票,以便那些缺失字段最少的人排在第一位。

我希望结果如下所示:

+-----------+---------------+------------+
| ticket_id | path_distance |    path    |
+-----------+---------------+------------+
|        12 |             3 |   14,32,78 |
+-----------+---------------+------------+
|         9 |             4 | 2,58,76,89 |
+-----------+---------------+------------+
... etc

【问题讨论】:

  • 您针对 1 行比赛的解决方案将最多列出每张票 3 次 - 即使它已经有整行。我不确定你是否想说:12 号票需要数字 14、32、78 才能赢得单排挑战赛,如果它已经赢了。不过,您也可以通过加入第二行来获得两行结果(第二次添加三个连接,以及条件r1.ticket_row_id &lt; r2.ticket_row_id)和group by r1.ticket_row_id, r2.ticket_row_id。如果您需要对路径进行排序,它会变得更复杂一些(您可以通过加入一个包含所有 90 个数字的虚拟表来实现)。
  • @solarflare 示例中的查询返回 path_distance 小于 4 的行,即使这意味着从单个票证返回多行 - 这是设计使然。但我不确定我是否完全理解您建议的附加连接的外观。你能举个例子吗?
  • 我的意思是:添加连接 inner join ticket_row r2 on r.ticket_id = t.id and r1.ticket_row_id != r.ticket_row_id inner join ticket_row_field f2 on f2.ticket_row_id = r.id left join called_number n2 on n2.game_id = t.game_id and and n2.called_number = f2.content 并调整您的条件和选择(例如添加 distinct)。如果您提供(简化的)表结构(在您的查询中包含字段)和一些示例数据,我可以做到。
  • 我无法让您的建议生效。我自己解决了这个问题,使用两个视图分别表示缺失的行和不缺失数字的行。

标签: mysql


【解决方案1】:

以下似乎是要走的路: 首先,我们创建了几个视图,以便更容易理解实际的选择查询

第一个视图表示已经完全填充的行 - 这意味着所有 5 个数字也已被调用。

create or replace view filled as
select 
    r.ticket_id, f.ticket_row_id, 0 path_distance
from 
    ticket_row_field f
    inner join ticket_row r
        on r.id = f.ticket_row_id
    inner join ticket t
        on t.id = r.ticket_id
    inner join called_number n
        on n.called_number = f.content
group by ticket_row_id
having count(*) = 5;

另一个视图表示未完全填充的行

create or replace view incomplete as
        select 
            r.ticket_id, f.ticket_row_id,
                coalesce(filled.path_distance, count(content)) path_distance,
                case when 
                    filled.path_distance is not null then 
                    '' else 
                    group_concat(content order by content) 
                end path
        from 
            ticket t
            inner join ticket_row r
                on r.ticket_id = t.id
            inner join ticket_row_field f
                on f.ticket_row_id = r.id
            left join called_number n
                on n.game_id = t.game_id
                and n.called_number = f.content
            left join filled
                on filled.ticket_row_id = f.ticket_row_id
        where 
            n.called_number is null or filled.ticket_row_id is not null
        group by 
            ticket_row_id;

然后我们使用以下选择查询来获取我们需要的票,包括它们的路径(= 缺少的数字)

select 
    r1.ticket_id, r1.path_distance + r2.path_distance distance_sum, concat(r1.path, ',', r2.path) path_combined
from 
    incomplete r1
        inner join incomplete r2
            on r2.ticket_id = r1.ticket_id
where 
    r2.ticket_row_id < r1.ticket_row_id
order by 
    distance_sum
limit 5;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多