Ищите совпадения в таблице

#sql #sql-server #tsql

Вопрос:

У меня есть таблица в SQL Server, в которой хранятся ковры. Каждый из них имеет свой собственный идентификатор и диапазон в метрах (от-до) с цветом.

 CREATE TABLE rugs (  [code] VARCHAR (10),   [from] INT,   [to] INT,  [color] VARCHAR (10) );  INSERT INTO rugs VALUES ('RUG001', 0, 1, 'Yellow'); INSERT INTO rugs VALUES ('RUG001', 1, 2, 'Red'); INSERT INTO rugs VALUES ('RUG001', 2, 4, 'Blue'); INSERT INTO rugs VALUES ('RUG001', 3, 5, 'Green'); INSERT INTO rugs VALUES ('RUG002', 0, 1, 'Purple'); INSERT INTO rugs VALUES ('RUG002', 1, 2, 'Orange');  

В этом примере он перекрывается в строках, соответствующих синему и зеленому цветам для ковра RUG001. RUG002 в порядке.

Как я могу проверить, для одного и того же ковра, есть ли интервалы с перекрытием?

То, что я пробовал (и это не работает)

 Select * from RUGS as R1 INNER JOIN RUGS as R2 ON R1.CODE = R2.CODE WHERE R1.[FROM] lt;= R2.[TO] AND R1.[TO] gt;= R2.[FROM]  

Комментарии:

1... WHERE R1.[from] lt; R2.[to] AND R1.[to] gt; R2.[from] and not(R1.[from] = R2.[from] and R1.[to] = R2.[to] and R1.color = R2.color)

Ответ №1:

Трудно быть уверенным с небольшим набором данных, но работает ли для вас следующее? Использование опережения/задержки для проверки того, попадает ли следующий или последний диапазон в текущий диапазон.

 with rug as ( select * ,  Lead([from]) over(partition by code order by [from]) nextfrom,   Lag([to]) over(partition by code order by [to]) lastto from rugs ) select code, [from], [to], color  from rug where nextfromlt;[to] or lasttogt;[from]  

Ответ №2:

Здесь у вас есть два возможных решения.

  1. Просто перекрытие с левой стороны:
 SELECT * FROM RUGS R1 INNER JOIN RUGS R2 ON R1.CODE = R2.CODE WHERE R1.[TO] lt; R2.[TO] AND R2.[FROM] lt; R1.[TO]   --Result /* code from to color code from to color RUG001 2 4 Blue RUG001 3 5 Green */  
  1. Все перекрытия:
 SELECT * FROM RUGS R1 INNER JOIN RUGS R2 ON R1.CODE = R2.CODE WHERE R1.[FROM] lt; R2.[FROM] AND R2.[TO] lt; R1.[TO]  OR (R2.[FROM] lt; R1.[FROM] AND R2.[TO] lt; R1.[TO] AND R1.[FROM] lt; R2.[TO]) OR (R1.[FROM] lt; R2.[FROM] AND R1.[TO] lt; R2.[TO] AND R2.[FROM] lt; R1.[TO])  -- Result /* code from to color code from to color RUG001 2 4 Blue RUG001 3 5 Green RUG001 3 5 Green RUG001 2 4 Blue */