使用 INTERSECT 进行矩阵查询
Matrix query using INTERSECT
我有代表真实世界物理位置的数据。从概念上讲,可以将其视为:
|--|---|---|---|---|---|
|1A| 2A| 3A| 4A| 5A| 6A|
|--|---|---|---|---|---|
|1B| 2B| 3B| 4B| 5B| 6B|
|--|---|---|---|---|---|
|1C| 2C| 3C| 4C| 5C| 6C|
|--|---|---|---|---|---|
|1D| 2D| 3D| 4D| 5D| 6D|
|--|---|---|---|---|---|
|1E| 2E| 3E| 4E| 5E| 6E|
|--|---|---|---|---|---|
|1F| 2F| 3F| 4F| 5F| 6F|
|--|---|---|---|---|---|
一起玩,这里是DDL/DML:
CREATE TABLE [dbo].[test](
[x] [int] NOT NULL,
[y] [char](10) NOT NULL,
CONSTRAINT [PK_test] PRIMARY KEY CLUSTERED
(
[x] ASC,
[y] ASC
)
) ON [PRIMARY]
GO
INSERT INTO Test(x,y) VALUES(1,'A');
INSERT INTO Test(x,y) VALUES(1,'B');
INSERT INTO Test(x,y) VALUES(1,'C');
INSERT INTO Test(x,y) VALUES(1,'D');
INSERT INTO Test(x,y) VALUES(1,'E');
INSERT INTO Test(x,y) VALUES(1,'F');
INSERT INTO Test(x,y) VALUES(2,'A');
INSERT INTO Test(x,y) VALUES(2,'B');
INSERT INTO Test(x,y) VALUES(2,'C');
INSERT INTO Test(x,y) VALUES(2,'D');
INSERT INTO Test(x,y) VALUES(2,'E');
INSERT INTO Test(x,y) VALUES(2,'F');
INSERT INTO Test(x,y) VALUES(3,'A');
INSERT INTO Test(x,y) VALUES(3,'B');
INSERT INTO Test(x,y) VALUES(3,'C');
INSERT INTO Test(x,y) VALUES(3,'D');
INSERT INTO Test(x,y) VALUES(3,'E');
INSERT INTO Test(x,y) VALUES(3,'F');
INSERT INTO Test(x,y) VALUES(4,'A');
INSERT INTO Test(x,y) VALUES(4,'B');
INSERT INTO Test(x,y) VALUES(4,'C');
INSERT INTO Test(x,y) VALUES(4,'D');
INSERT INTO Test(x,y) VALUES(4,'E');
INSERT INTO Test(x,y) VALUES(4,'F');
INSERT INTO Test(x,y) VALUES(5,'A');
INSERT INTO Test(x,y) VALUES(5,'B');
INSERT INTO Test(x,y) VALUES(5,'C');
INSERT INTO Test(x,y) VALUES(5,'D');
INSERT INTO Test(x,y) VALUES(5,'E');
INSERT INTO Test(x,y) VALUES(5,'F');
INSERT INTO Test(x,y) VALUES(6,'A');
INSERT INTO Test(x,y) VALUES(6,'B');
INSERT INTO Test(x,y) VALUES(6,'C');
INSERT INTO Test(x,y) VALUES(6,'D');
INSERT INTO Test(x,y) VALUES(6,'E');
INSERT INTO Test(x,y) VALUES(6,'F');
事实上,矩阵将超过一百万 X 百万,但如果我能解决这个问题,我将能够将它应用到我的应用程序中。我的程序存在的问题是要显示给他们使用的数据量。因为在这个矩阵中,他们总是对数据网格的外围感兴趣,所以我为他们提供了在网格的四个边之一上查看数据子集的选项。这是由 Top 过滤器和 Order by 子句管理的。
我无法使用 x 或 y 的数据值。只有他们如何整理。
例如
select top 2 *
from test
order by y
returns 上面绘制的矩阵的前两行。
按 y desc returns 底部两行排序
order by x asc returns 左边两行
order by x desc returns 右边两行
上述查询使难以管理的情况变得更易于管理,但现在他们想要更多。
有人问我有没有办法读取矩阵的角
|1D| 2D| 3D|
|--|---|---|
|1E| 2E| 3E|
|--|---|---|
|1F| 2F| 3F|
|--|---|---|
似乎相交可以解决问题,但我没有找到成功。我已经尝试过与递归连接相交,但我没有任何运气。
看来我可以查询前 3 行和左边 3 行,然后 return 仅查询具有相同值的行,即交集,但我一直返回完整行。
select top 6 t1.x, t1.y
from test t1
inner join test t2 on (t1.x = t2.x) and (t1.y = t2.y)
intersect
select top 6 t2.x, t2.y
from test t2
inner join test t1 on (t1.x = t2.x) and (t1.y = t2.y)
这似乎很接近,如果我能让一个 Order by 子句在两个 Selects 中都起作用的话。
感谢任何帮助。
如果你想要角落,为什么不按两列排序?对于左上角:
select top 1 *
from test
order by x, y;
使用 asc
和 desc
,视其他角而定。这可以很好地利用 x, y
.
上的索引
如果您想要某个角的正方形中的单元格,那么您可以这样做:
select t.*
from test t
where t.x in (select top 3 t2.x from test t2 group by t2.x order by t2.x) and
t.y in (select top 3 t2.y from test t2 group by t2.y order by t2.y);
这利用了两个索引,test(x, y)
和 test(y, x)
。
再次在子查询中使用asc
和desc
来定义哪个角。
这是使用 row_number()
给每个单元格一个 x,y 坐标的另一种方法,它允许您通过在 where 子句中指定坐标 select 角
select * from (
select * ,
row_number() over (partition by y order by x) xn,
row_number() over (partition by x order by y) yn
from test
) t where xn = 1 and yn = 4
假设每行 6 个单元格,上面的查询 returns 第一个 3x3 矩阵的左上角在第二行矩阵中,即 1D
。通常,要在矩阵的 kth
行中检索 nth
矩阵(大小 mxm
)的左上角,您可以使用:where xn = ((n-1)*m)+1 and yn = ((k-1)*m)+1
要检索 3x3 矩阵的所有左上角,您可以使用 %
运算符 where xn%3 = 1 and yn%3 = 1
我有代表真实世界物理位置的数据。从概念上讲,可以将其视为:
|--|---|---|---|---|---|
|1A| 2A| 3A| 4A| 5A| 6A|
|--|---|---|---|---|---|
|1B| 2B| 3B| 4B| 5B| 6B|
|--|---|---|---|---|---|
|1C| 2C| 3C| 4C| 5C| 6C|
|--|---|---|---|---|---|
|1D| 2D| 3D| 4D| 5D| 6D|
|--|---|---|---|---|---|
|1E| 2E| 3E| 4E| 5E| 6E|
|--|---|---|---|---|---|
|1F| 2F| 3F| 4F| 5F| 6F|
|--|---|---|---|---|---|
一起玩,这里是DDL/DML:
CREATE TABLE [dbo].[test](
[x] [int] NOT NULL,
[y] [char](10) NOT NULL,
CONSTRAINT [PK_test] PRIMARY KEY CLUSTERED
(
[x] ASC,
[y] ASC
)
) ON [PRIMARY]
GO
INSERT INTO Test(x,y) VALUES(1,'A');
INSERT INTO Test(x,y) VALUES(1,'B');
INSERT INTO Test(x,y) VALUES(1,'C');
INSERT INTO Test(x,y) VALUES(1,'D');
INSERT INTO Test(x,y) VALUES(1,'E');
INSERT INTO Test(x,y) VALUES(1,'F');
INSERT INTO Test(x,y) VALUES(2,'A');
INSERT INTO Test(x,y) VALUES(2,'B');
INSERT INTO Test(x,y) VALUES(2,'C');
INSERT INTO Test(x,y) VALUES(2,'D');
INSERT INTO Test(x,y) VALUES(2,'E');
INSERT INTO Test(x,y) VALUES(2,'F');
INSERT INTO Test(x,y) VALUES(3,'A');
INSERT INTO Test(x,y) VALUES(3,'B');
INSERT INTO Test(x,y) VALUES(3,'C');
INSERT INTO Test(x,y) VALUES(3,'D');
INSERT INTO Test(x,y) VALUES(3,'E');
INSERT INTO Test(x,y) VALUES(3,'F');
INSERT INTO Test(x,y) VALUES(4,'A');
INSERT INTO Test(x,y) VALUES(4,'B');
INSERT INTO Test(x,y) VALUES(4,'C');
INSERT INTO Test(x,y) VALUES(4,'D');
INSERT INTO Test(x,y) VALUES(4,'E');
INSERT INTO Test(x,y) VALUES(4,'F');
INSERT INTO Test(x,y) VALUES(5,'A');
INSERT INTO Test(x,y) VALUES(5,'B');
INSERT INTO Test(x,y) VALUES(5,'C');
INSERT INTO Test(x,y) VALUES(5,'D');
INSERT INTO Test(x,y) VALUES(5,'E');
INSERT INTO Test(x,y) VALUES(5,'F');
INSERT INTO Test(x,y) VALUES(6,'A');
INSERT INTO Test(x,y) VALUES(6,'B');
INSERT INTO Test(x,y) VALUES(6,'C');
INSERT INTO Test(x,y) VALUES(6,'D');
INSERT INTO Test(x,y) VALUES(6,'E');
INSERT INTO Test(x,y) VALUES(6,'F');
事实上,矩阵将超过一百万 X 百万,但如果我能解决这个问题,我将能够将它应用到我的应用程序中。我的程序存在的问题是要显示给他们使用的数据量。因为在这个矩阵中,他们总是对数据网格的外围感兴趣,所以我为他们提供了在网格的四个边之一上查看数据子集的选项。这是由 Top 过滤器和 Order by 子句管理的。
我无法使用 x 或 y 的数据值。只有他们如何整理。
例如
select top 2 *
from test
order by y
returns 上面绘制的矩阵的前两行。
按 y desc returns 底部两行排序
order by x asc returns 左边两行
order by x desc returns 右边两行
上述查询使难以管理的情况变得更易于管理,但现在他们想要更多。
有人问我有没有办法读取矩阵的角
|1D| 2D| 3D|
|--|---|---|
|1E| 2E| 3E|
|--|---|---|
|1F| 2F| 3F|
|--|---|---|
似乎相交可以解决问题,但我没有找到成功。我已经尝试过与递归连接相交,但我没有任何运气。
看来我可以查询前 3 行和左边 3 行,然后 return 仅查询具有相同值的行,即交集,但我一直返回完整行。
select top 6 t1.x, t1.y
from test t1
inner join test t2 on (t1.x = t2.x) and (t1.y = t2.y)
intersect
select top 6 t2.x, t2.y
from test t2
inner join test t1 on (t1.x = t2.x) and (t1.y = t2.y)
这似乎很接近,如果我能让一个 Order by 子句在两个 Selects 中都起作用的话。
感谢任何帮助。
如果你想要角落,为什么不按两列排序?对于左上角:
select top 1 *
from test
order by x, y;
使用 asc
和 desc
,视其他角而定。这可以很好地利用 x, y
.
如果您想要某个角的正方形中的单元格,那么您可以这样做:
select t.*
from test t
where t.x in (select top 3 t2.x from test t2 group by t2.x order by t2.x) and
t.y in (select top 3 t2.y from test t2 group by t2.y order by t2.y);
这利用了两个索引,test(x, y)
和 test(y, x)
。
再次在子查询中使用asc
和desc
来定义哪个角。
这是使用 row_number()
给每个单元格一个 x,y 坐标的另一种方法,它允许您通过在 where 子句中指定坐标 select 角
select * from (
select * ,
row_number() over (partition by y order by x) xn,
row_number() over (partition by x order by y) yn
from test
) t where xn = 1 and yn = 4
假设每行 6 个单元格,上面的查询 returns 第一个 3x3 矩阵的左上角在第二行矩阵中,即 1D
。通常,要在矩阵的 kth
行中检索 nth
矩阵(大小 mxm
)的左上角,您可以使用:where xn = ((n-1)*m)+1 and yn = ((k-1)*m)+1
要检索 3x3 矩阵的所有左上角,您可以使用 %
运算符 where xn%3 = 1 and yn%3 = 1