4

我有一个游戏桌,例如:

CREATE TABLE game_piece(
  x Integer,
  y Integer,
  type Integer
);

每个 (x,y) 只能有 1 件。表示一个网格(数字是类型):

1235
1134
9678

通过连接,我的意思是它们必须以垂直或水平方式直接靠近原点,例如:

 C   C=connected
COC  O=origin
 C

如果有合适的解决方案,我想检查网格上是否有 3 个部分连接,而无需获取数据库的整个网格并在 python 中进行操作。建议?

4

5 回答 5

3

为了澄清我对 Xophmeister 答案的评论,如下所示:

SELECT o.x, o.y
FROM game_piece o
JOIN game_piece p
ON p.type = o.type
AND (
  (o.x = p.x AND p.y IN (o.y-1,o.y+1))
  OR
  (o.y = p.y AND p.x IN (o.x-1,o.x+1))
)
GROUP BY o.x, o.y
HAVING COUNT(*) > 1

它正在处理您的测试数据:http ://sqlfiddle.com/#!3/0bd34/1

编辑:由于您只想知道条件是否存在,因此最好的方法是推LIMIT 1到最后,看看查询是否返回结果。出于某种原因,sqlfiddle 不喜欢我将 LIMIT 放在那里,但我在我的服务器上对其进行了测试,它工作得很好。

于 2012-07-12T08:21:53.207 回答
1

通过“连接”,我将假设您的意思是相邻的:也就是说,(5,3,1234)和(4,3,1234)将被连接。

因此,您可以将表连接到自身两次,其中每个连接取决于之前的连接,条件包括:

on  nextPiece.type = lastPiece.type
and (nextPiece.x in (lastPiece.x - 1, lastPiece.x + 1)
or  nextPiece.y in (lastPiece.x - 1, lastPiece.x + 1))

请注意,这并不认为对角线是相邻的。

这种技术的问题在于它会返回重复项:如果记录 A 连接到记录 B,那么 A 和 B 都将显示在结果集中。当您加入两次时,您会看到三个重复项...select distinct如果您感兴趣的只是您是否找到匹配项,您可以做一个,但是查询通常不会特别快(取决于你的网格有多大,填充的有多稀疏)。

编辑见 Braiba 的解决方案(和评论,下面):我犯了一个错误:P

于 2012-07-12T07:43:39.890 回答
0

根据连接的含义,您不需要转储整个数据库,而只需转储 4 个方向上的 2 个。

select x, y, 
from game_piece 
where (
       (x between origin_x - 2 AND origin_x + 2 AND y = origin_y) 
    OR (y between origin_y - 2 AND origin_y + 2 AND x = origin_x)
      ) 
 AND type = the_type;

origin_x,origin_y是您要检查的棋子的坐标。

这将转储 1 到 8 件,您必须检查。

如果游戏表非常大,您应该在 x 和 y 列上添加索引,否则可能没有用。

希望能帮助到你。

M。

于 2012-07-12T07:44:57.657 回答
0

这将返回不同连接类型的数量:

select count(distinct type) as connections
from game_piece
where ((y = $y and x between $x - 1 and $x + 1)
  or (x = $x and y between $y - 1 and $y + 1))
and (x != $x or y != $y) -- exclude the origin itself
于 2012-07-12T07:47:01.337 回答
0

您可以使用此解决方案:

SELECT 1
FROM game_piece
WHERE
    (x = $o_x AND y IN ($o_y + 1, $o_y - 1)) OR
    (y = $o_y AND x IN ($o_x + 1, $o_x - 1))
GROUP BY type
HAVING COUNT(1) = 3

$o_x分别$o_y是 originX 和 originY 输入参数。

如果恰好有 3 个相同类型的片段连接到原点(垂直或水平),则返回1,否则返回空结果集。


编辑:

您可以尝试什么来确定网格上是否有任何块具有 2 个或多个相同的相邻类型:

SELECT COUNT(1) > 0 AS doesExist
FROM
(
    SELECT 1
    FROM game_piece p
    INNER JOIN game_piece o ON
         p.type = o.type AND (
             (p.x = o.x AND p.y IN (o.y + 1, o.y - 1)) OR
             (p.y = o.y AND p.x IN (o.x + 1, o.x - 1))
         )
    GROUP BY p.type, o.x, o.y
    HAVING COUNT(1) > 1
) a

1如果有一件或多件,则返回,否则返回0

于 2012-07-12T08:01:22.517 回答