使用INTERSECT进行矩阵查询

时间:2015-10-17 14:18:04

标签: sql tsql matrix 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的数据值。只有他们如何整理。

e.g。

  select top 2 *
  from test 
  order by y 

返回上面绘制的矩阵的前两行。 按y desc排序返回底部的两行 按x的顺序asc返回左边的两行
order by x desc返回正确的两行

上述查询使无法管理的情况更易于管理,但现在他们想要更多。

我被问到是否有任何方法可以在矩阵的角落阅读。

|1D| 2D| 3D|
|--|---|---|
|1E| 2E| 3E|
|--|---|---|
|1F| 2F| 3F|
|--|---|---|

似乎交叉可以解决这个问题,但我找不到成功。我尝试过与递归连接的交叉,我没有运气。

你似乎我可以查询前3行和左3行,然后只返回那些具有相同值的那些,即交集,但我不断回到完整的行。

  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子句,那么这似乎很接近。

任何帮助表示感谢。

2 个答案:

答案 0 :(得分:1)

如果你想要角落,为什么不只是按两列排序?左上角:

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来定义哪个角落。

答案 1 :(得分:0)

这是使用row_number()为每个单元格提供x,y坐标的另一种方法,它允许您通过在where子句中指定坐标来选择角点

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个单元格,上面的查询返回第二行矩阵中第一个3x3矩阵的左上角,即1D。通常,要检索nth矩阵行中mxm矩阵(大小kth)的左上角,您可以使用:where xn = ((n-1)*m)+1 and yn = ((k-1)*m)+1

要检索3x3矩阵的所有左上角,您可以使用%运算符where xn%3 = 1 and yn%3 = 1