Как рассчитать с SQL сгруппированы по ячейкам в сетке? - PullRequest
0 голосов
/ 29 октября 2018

Я использую SQL и хочу подсчитать количество точек в сетке различной размерности.

Я нашел решение, но мне интересно, может ли быть более элегантный или эффективный способ сделать это с акцентом на Oracle.

Это моя база данных:

create table tmpa (
  x number(10, 2),
  y number(10, 2),
  val number
);

insert into tmpa values (1.0, 1.8, 9);
insert into tmpa values (1.9, 2.0, 9);
insert into tmpa values (2.1, 1.9, 9);
insert into tmpa values (2.2, 2.6, 9);
insert into tmpa values (2.6, 2.7, 9);
insert into tmpa values (3.1, 3.9, 9);
insert into tmpa values (3.4, 3.7, 9);
insert into tmpa values (3.7, 3.8, 9);

Предположим, что x и y правильно проиндексированы. Это примерно соответствует точкам на плоскости.

Теперь я хочу посчитать количество точек в ячейках сетки. Сетка начинается в (xmin,ymin) и заканчивается (xmax,ymax) каждая, разделенная на cells части.

Пример может выглядеть так:

  |       |       |       |
--+-------+-------+-------+-- 4.7
  |       |       |       |
  |       |    *  |       |
  |       |     * | *     |
--+-------+-------+-------+-- 3.5
  |       |       |       |
  |       |  *    |       |
  |     * |       |       |
--+-------+-------+-------+-- 2.3
  |       |       |       |
o |    ** |       |       |
  |       |       |       |
--+-------+-------+-------+-- 1.1
  |       |       |       |
 1.1     2.3     3.5     4.7

cells здесь 3, xmin и ymin равно 1.1, xmax и ymax равно 4.7, что приводит к размеру ячейки (dx и dy ) из 1.2.

Теперь я хочу посчитать количество точек в каждой ячейке. Для удобства я также могу получить центральную точку в результате запроса.

Результат будет выглядеть так:

xcell ycell COUNT   center
  0,    0,    2,   1.65,1.65
  0,    1,    1,   1.65,2.85
  1,    1,    1,   2.85,2.85
  1,    2,    2,   2.85,4.05
  2,    2,    1    4.05,4.05

Я бы тоже не против, чтобы в списке были указаны строки с нулем.

Это именно то, что выводит следующий запрос:

-- 1.1: xmin, 4.7: xmax, cells:3, 1.2:(xmax-xmin)/cells ; same with y
Select d2.xcell, d2.ycell, d2.cnt, d2.xcell*1.2+1.1+1.1/2 xcenter, d2.ycell*1.2+1.1+1.1/2 ycenter
From (
  SELECT d1.xcell, d1.ycell, count(*) cnt
  FROM (
    select floor((x-1.1)/1.2) xcell, floor((y-1.1)/1.2) ycell
    from tmpa
  ) d1
  where d1.xcell>=1.1 and d1.xcell<4.7 and d1.ycell>=1.1 and d1.ycell<4.7
  group by xcell, ycell
) d2
Order By d2.xcell, d2.ycell
;

Но это сложнее, чем я думал. И я не знаю, насколько это эффективно. Может быть, есть очень эффективный или очень простой запрос, который я просто не вижу.

Примечание: я не хочу использовать гео- или пространственные расширения.

Обновление: Я удалил between, потому что >= и < лучше для полуоткрытых интервалов.

1 Ответ

0 голосов
/ 29 октября 2018

Это эквивалентно вашему запросу, но без некоторых подзапросов подзапросов:

select xcell, ycell, cnt, xcell*1.2+1.1+1.1/2 as xcenter, ycell*1.2+1.1+1.1/2 ycenter
from (select floor((x-1.1)/1.2) as xcell, floor((y-1.1)/1.2) as ycell, count(*) as cnt
      from tmpa
      where xcell >= 1.1 and xcell < 4.7 and 
            ycell >= 1.1 and ycell < 4.7
      group by floor((x-1.1)/1.2), floor((y-1.1)/1.2)
     ) d
order By xcell, ycell;

Это также исправило проблему границ, заменив between на соответствующие неравенства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...