Как выбрать строки по диапазону? - PullRequest
0 голосов
/ 27 мая 2019

У меня есть следующая таблица с именем 'T'

enter image description here

Мой желаемый результат должен быть следующим,

enter image description here

Я хочу выбрать те строки, в которых столбец 'Фактический' должен иметь диапазон между столбцом 'Базовый' , однако, если вы берете пример для 'Модель' = HT65 'Actual' = 23.2 с диапазоном от 22 до 24 столбца 'Basic' , поэтому я должен получить следующую строку, где столбец 'Level' равен 2

enter image description here

Аналогично должны быть выбраны другие строки. Ваша помощь будет оценена.

1 Ответ

1 голос
/ 27 мая 2019

Вы можете использовать следующее решение, используя несколько LEFT JOIN, чтобы присоединиться к следующей и последней строке текущей строки. С некоторыми дополнительными условиями вы можете проверить диапазон:

SELECT t1.Model, t1.Level, t1.Basic, t1.Actual
FROM (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY Model ORDER BY Basic) AS rn 
  FROM test
) t1 LEFT JOIN (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY Model ORDER BY Basic) AS rn 
  FROM test
) t2 ON t1.Model = t2.Model AND t1.rn + 1 = t2.rn LEFT JOIN (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY Model ORDER BY Basic) AS rn 
  FROM test
) t3 ON t1.Model = t3.Model AND t1.rn - 1 = t3.rn
WHERE (t1.Actual BETWEEN t3.Basic AND t1.Basic)
  OR (t3.Model IS NULL AND t1.Actual < t1.Basic)
  OR (t2.Model IS NULL AND t1.Actual > t1.Basic)
ORDER BY t1.Model ASC

Приведенный выше запрос возвращает все ожидаемые строки. Я также добавил несколько дополнительных случаев, чтобы улучшить запрос для этих (особых) случаев. Вышеупомянутое решение работает с SQL-Server 2008.


Начиная с SQL-Server 2012, вы можете использовать следующее решение, используя LAG и LEAD:

SELECT t.Model, t.Level, t.Basic, t.Actual
FROM (
  SELECT *, LAG(Basic, 1,0) OVER (PARTITION BY Model ORDER BY Basic) AS prevBasic,
    LEAD(Basic, 1, 0) OVER (PARTITION BY Model ORDER BY Basic) AS nextBasic
  FROM test 
) t 
WHERE (t.Actual BETWEEN t.prevBasic AND t.Basic)
   OR (t.nextBasic = 0 AND t.Actual > t.Basic)
ORDER BY t.Model ASC

демо на dbfiddle.uk

...