Подтвердить что ты не робот

Набор основанного подхода для удаления содержащихся точек

У меня есть эти данные:

IF OBJECT_ID('tempdb..#temp') IS NOT NULL
    DROP TABLE #temp
CREATE TABLE #temp
    (
      Id INT IDENTITY(1, 1) ,
      X FLOAT NOT NULL ,
      Y FLOAT NOT NULL
    )

INSERT INTO #temp (X, Y) VALUES (0, 0)
INSERT INTO #temp (X, Y) VALUES (0, 1)
INSERT INTO #temp (X, Y) VALUES (0, 2)
INSERT INTO #temp (X, Y) VALUES (0.5, 1)
INSERT INTO #temp (X, Y) VALUES (1, 1)
INSERT INTO #temp (X, Y) VALUES (1, 2)
INSERT INTO #temp (X, Y) VALUES (1.5, 0.5)
INSERT INTO #temp (X, Y) VALUES (2, 0)
INSERT INTO #temp (X, Y) VALUES (2, 1)

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

(0, 1)
(1, 1)
(1.5, 0.5)

для получения внешнего большинства точек, которые определяют внешний многоугольник, состоящий только из вертикальных и горизонтальных линий без избыточности (например, (0, 1), является избыточной точкой). Может ли это быть достигнуто с помощью подхода TSQL на основе набора в SQL Server 2014?

PS:

График рассеяния данных выглядит следующим образом:

enter image description here

Я хотел бы удалить окруженные точки. В конечном счете, я за внешней границей (рисуется красным цветом). Надеюсь, это делает его более ясным.

4b9b3361

Ответ 1

Я считаю, что это может сработать. Кажется, это доставляет ваши тестовые данные. Немного грубо. Некоторые из SELECT MIN и SELECT MAX, возможно, могут быть рассчитаны заранее, если ваши реальные данные велики.

SELECT * 
-- uncomment this to delete the desired points
-- DELETE #temp
FROM #temp t
WHERE 
(
    -- Internal points
    (
            ( X > (SELECT MIN(X) FROM #temp) AND X < (SELECT MAX(X) FROM #temp) )
        AND ( Y > (SELECT MIN(Y) FROM #temp) AND Y < (SELECT MAX(Y) FROM #temp) )
    )
    -- Exceptions (points with nothing strictly outside them) [Don't want to lose (1,1)]
    AND EXISTS (SELECT * FROM #temp WHERE X > t.X AND Y > t.Y)
)
OR
    -- redundant edge points [(0,1) would be included as an "exception"]
(
    ( (t.X = (SELECT MIN(X) FROM #temp) OR t.X = (SELECT MAX(X) FROM #temp)) 
        AND EXISTS (SELECT * FROM #temp WHERE X = t.X AND Y > t.Y) 
        AND EXISTS (SELECT * FROM #temp WHERE X = t.X AND Y < t.Y)  )
    OR
    ( (t.Y = (SELECT MIN(Y) FROM #temp) OR t.Y = (SELECT MAX(Y) FROM #temp)) 
        AND EXISTS (SELECT * FROM #temp WHERE Y = t.Y AND X > t.X) 
        AND EXISTS (SELECT * FROM #temp WHERE Y = t.Y AND X < t.X)  )
)