【问题标题】:Find empty positions in a grid在网格中查找空位置
【发布时间】:2017-09-01 12:41:36
【问题描述】:

Contents 表中,项目存储在 X、Y 坐标中:

Contents
-------
id
parent_id
pos_x
pos_y

假设容器大小为 3 x 3。我想找出给定容器中的哪些位置是空闲的。到目前为止,我已经生成了一个二维矩阵:

SELECT *
FROM 
    (SELECT rownum X FROM dual  CONNECT BY LEVEL <= 3 ) xaxis
INNER JOIN 
    (SELECT rownum Y FROM dual  CONNECT BY LEVEL <=3 ORDER BY 1) yaxis
ON xaxis.X <> yaxis.Y OR xaxis.X = yaxis.Y

然后我尝试将 JOIN 查询放在一起,不包括 Contents 中存在的 X、Y 位置:

SELECT X, Y
FROM 
    (SELECT rownum X FROM dual  CONNECT BY LEVEL <= 3 ) xaxis
INNER JOIN 
    (SELECT rownum Y FROM dual  CONNECT BY LEVEL <=3 ORDER BY 1) yaxis
ON xaxis.X <> yaxis.Y OR xaxis.X = yaxis.Y

INNER JOIN (
    SELECT pos_x, pos_y FROM Contents WHERE parent_id = ?) items
ON items.posx <> xaxis.X AND items.posy <> yaxis.Y;

这不会将每一对视为唯一的,并且如果位置已被占用,则会从 所有 行中排除值。比如假设(2, 2)被占用,上面的返回:

X   Y
-----
1   1
1   3
3   1
3   3

本质上,我试图找出两组的差异。任何帮助表示赞赏。

【问题讨论】:

  • @bradimus 后端是 Java,但你是对的,它应该被删除。已编辑。谢谢

标签: oracle11g set-theory


【解决方案1】:

我在发布问题之前就想出了答案,所以我想我会同时发布并回答。将问题陈述为获取两组的差异让我朝着正确的方向前进。

答案是MINUS 运算符。将最后的 JOIN 替换为 MINUS 即可得到预期的结果:

select X, Y
from 
    (select rownum X from dual  CONNECT BY LEVEL <= 3 ) xaxis
inner join 
    (select rownum Y from dual  CONNECT BY LEVEL <=3 order by 1) yaxis
on xaxis.X <> yaxis.Y OR xaxis.X = yaxis.Y

MINUS

select pos_x, pos_y FROM Contents WHERE parent_id = ?;

返回预期结果(注意缺少(2, 2)):

X   Y
-----
1   1
1   2
1   3
2   1
2   3
3   1
3   2
3   3

今天是个好日子

【讨论】:

  • 我认为您的内部联接应该只是交叉联接?而且,yaxis 子查询中不需要order by 1
【解决方案2】:

您可以使用外部联接而不是减号来执行此操作(尽管您必须同时测试两者才能找出哪个更适合您的数据!)。

如果您一次只为一个 parent_id 执行此操作,您会这样做:

WITH CONTENTS AS (SELECT 1 parent_id, 2 pos_x, 2 pos_y FROM dual UNION ALL
                  SELECT 2 parent_id, 2 pos_x, 1 pos_y FROM dual)
SELECT xaxis.x,
       yaxis.y
FROM   ((SELECT LEVEL x FROM dual CONNECT BY LEVEL <= 3) xaxis
        CROSS JOIN (SELECT LEVEL y FROM dual CONNECT BY LEVEL <= 3) yaxis)
       LEFT OUTER JOIN CONTENTS c ON c.pos_x = xaxis.x AND c.pos_y = yaxis.y AND c.parent_id = 1
WHERE  c.parent_id IS NULL
ORDER BY x, y;

         X          Y
---------- ----------
         1          1
         1          2
         1          3
         2          1
         2          3
         3          1
         3          2
         3          3

或者,如果你想为所有 parent_id 运行它,你可以像这样使用partitioned outer join

WITH CONTENTS AS (SELECT 1 parent_id, 2 pos_x, 2 pos_y FROM dual UNION ALL
                  SELECT 2 parent_id, 2 pos_x, 1 pos_y FROM dual)
SELECT c.parent_id,
       xaxis.x,
       yaxis.y
FROM   ((SELECT LEVEL x FROM dual CONNECT BY LEVEL <= 3) xaxis
        CROSS JOIN (SELECT LEVEL y FROM dual CONNECT BY LEVEL <= 3) yaxis)
       LEFT OUTER JOIN CONTENTS c PARTITION BY (c.parent_id) ON c.pos_x = xaxis.x AND c.pos_y = yaxis.y
WHERE  c.pos_x IS NULL
AND    c.pos_y IS NULL
ORDER BY c.parent_id,
         xaxis.x,
         yaxis.y;

 PARENT_ID          X          Y
---------- ---------- ----------
         1          1          1
         1          1          2
         1          1          3
         1          2          1
         1          2          3
         1          3          1
         1          3          2
         1          3          3
         2          1          1
         2          1          2
         2          1          3
         2          2          2
         2          2          3
         2          3          1
         2          3          2
         2          3          3

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2018-08-21
    • 2011-03-25
    相关资源
    最近更新 更多