在网格中查找空位置
Find empty positions in a grid
在 Contents
table 中,项目存储在 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)
被占用,上面的returns:
X Y
-----
1 1
1 3
3 1
3 3
本质上,我是想找出两组的不同之处。任何帮助表示赞赏。
我在 post 提出问题之前想出了答案,所以我认为我会 post 同时回答它。将问题描述为 得到两组的差异 让我朝着正确的方向前进。
答案是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 = ?;
哪个 returns 预期结果(注意缺少 (2, 2)
):
X Y
-----
1 1
1 2
1 3
2 1
2 3
3 1
3 2
3 3
今天是个好日子
您可以使用外部联接而不是减号来执行此操作(尽管您必须测试两者以找出哪个对您的数据性能更高!)。
如果你一次只为一个 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 s,你可以使用 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
在 Contents
table 中,项目存储在 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
:
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)
被占用,上面的returns:
X Y
-----
1 1
1 3
3 1
3 3
本质上,我是想找出两组的不同之处。任何帮助表示赞赏。
我在 post 提出问题之前想出了答案,所以我认为我会 post 同时回答它。将问题描述为 得到两组的差异 让我朝着正确的方向前进。
答案是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 = ?;
哪个 returns 预期结果(注意缺少 (2, 2)
):
X Y
-----
1 1
1 2
1 3
2 1
2 3
3 1
3 2
3 3
今天是个好日子
您可以使用外部联接而不是减号来执行此操作(尽管您必须测试两者以找出哪个对您的数据性能更高!)。
如果你一次只为一个 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 s,你可以使用 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