2015-10-17 4 views
0

У меня есть данные, которые представляют реальные физические местоположения в реальном мире. Концептуально, можно было смотреть на него, как:Матричный запрос с использованием 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 

возвращает верхние два ряда матрицы, вычерченные выше. порядка по у убыв возвращает две нижние строки порядка по х возрастанию возвращает левые два ряда
порядка по х по алфавиту возвращает правильные две строки

вышеуказанных запросов сделали неуправляемым ситуацию более управляемой, но теперь они хотят больше ,

Меня спросили, есть ли способ прочитать в углу матрицы.

|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 для работы в обоих вариантах.

Любая помощь приветствуется.

+0

Я понимаю, что означает угол, когда вы хотите ровно одну ячейку. Почему у вас есть «топ-6»? –

ответ

1

Если вам нужны углы, почему бы не просто заказать две колонки? Для верхнего левого угла:

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 в подзапросе, чтобы определить, какой из углов.

+0

спасибо Гордон. Вы спасли меня с простотой. –

0

Вот еще один способ использования row_number(), чтобы дать каждой ячейке в х, у координаты, что позволяет выбрать углы, указав координаты в пункте где

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

+0

Я не следую за тобой. Не могли бы вы перейти к следующему логическому шагу? –

Смежные вопросы