使用 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;

使用 ascdesc,视其他角而定。这可以很好地利用 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)

再次在子查询中使用ascdesc来定义哪个角。

这是使用 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