假设我有一个包含以下格式的表:
| dbo.ROUTES |
----------------------------------------
| ID | ROUTE | LOWER_LIMIT | UPPER_LIMIT |
----------------------------------------
| 0 | A | 0 | 10 |
| 1 | B | 11 | 500 |
| 2 | C | 600 | 1000 |
如何找到路径条目未涵盖的任何数字范围?即对于上面的例子,我需要能够看到没有包含501 - 599的条目。
我们目前正在使用这种布局,虽然有4或5个其他具有各种标准的列,我们已经发现(正如您所期望的)因为表已经增长,并且已经更新了下限和上限阈值,我们开始看到空洞和重叠。
我知道这实际上归结为糟糕的设计,但在我们有资源改进它之前,我们可以做一些过时的事情,至少可以帮助我们手动整理表格。
谢谢,
答案 0 :(得分:1)
由于你不能使用超前/滞后功能,我已经使用了替代方法来实现这一点。根据需要通过添加/减去1
来编辑输出列(missing_val,重叠)中的边界条件输入:
ID LOWER_LIMIT UPPER_LIMIT
0 0 10
1 11 500
2 600 1000
3 980 1100
输出:
ID LOWER_LIMIT UPPER_LIMIT MISSING_VAL OVERLAPPING
0 0 10 0 0
1 11 500 500-600 0
2 600 1000 0 980-1000
3 980 1100 0 0
查询:
SELECT ID, LOWER_LIMIT, UPPER_LIMIT, CASE WHEN
UPPER_LIMIT+1=NEXT_LOWER_VAL THEN '0'
WHEN UPPER_LIMIT+1< NEXT_LOWER_VAL THEN
UPPER_LIMIT||'-'||NEXT_LOWER_VAL ELSE '0' END AS MISSING_VAL,
CASE WHEN
UPPER_LIMIT+1= NEXT_LOWER_VAL THEN '0'
WHEN UPPER_LIMIT+1> NEXT_LOWER_VAL THEN NEXT_LOWER_VAL||'-'||UPPER_LIMIT ELSE '0' END AS OVERLAPPING
FROM
(
SELECT T1.*, (SELECT MIN(LOWER_LIMIT) FROM TEST_T T WHERE T.ID<> T1.ID AND T.LOWER_LIMIT> T1.LOWER_LIMIT) AS NEXT_LOWER_VAL
FROM TEST_T T1) SUB
答案 1 :(得分:0)
这应该显示在其两侧都有间隙的行:
SELECT * FROM ROUTES
WHERE NOT Exists(SELECT ID FROM ROUTES as sub
WHERE sub.Lower_Limit = ROUTES.Upper_Limit + 1)
OR NOT Exists(SELECT ID FROM ROUTES as sub1
WHERE sub1.Upper_Limit = ROUTES.Lower_Limit - 1)
答案 2 :(得分:0)
由于您使用的是SQL Server 2008,因此无法使用LEAD
和LAG
函数,因此您需要自行加入:
SELECT T2.UPPER_LIMIT + 1 AS R1
,T1.LOWER_LIMIT - 1 AS R2
FROM (SELECT ROW_NUMBER() OVER(ORDER BY ID) AS RID
,ID
,ROUTE
,LOWER_LIMIT
,UPPER_LIMIT
FROM ROUTES) AS T1
LEFT JOIN (SELECT ROW_NUMBER() OVER(ORDER BY ID) AS RID
,ID
,ROUTE
,LOWER_LIMIT
,UPPER_LIMIT
FROM ROUTES) AS T2
ON T1.RID = T2.RID + 1
WHERE T1.LOWER_LIMIT - T2.UPPER_LIMIT > 1;
在SQL Server 2012 +中:
SELECT LAG_UPPER_LIMIT + 1 AS R1
,LOWER_LIMIT - 1 AS R2
FROM (SELECT ID
,ROUTE
,LOWER_LIMIT
,UPPER_LIMIT
,LAG(UPPER_LIMIT) OVER (ORDER BY ID) AS LAG_UPPER_LIMIT
FROM ROUTES) AS T
WHERE T.LOWER_LIMIT - T.LAG_UPPER_LIMIT > 1
这为您提供了完全缺失的范围。
答案 3 :(得分:0)
您要查找的是upper_limit
值与任何内容不重叠以及下一个lower_limit
值。实际上,您需要一个超过上限值而一个小于下一个下限值:
select r.upper_limit + 1 as missing_lower,
(select min(lower_limit) - 1
from routes r3
where r3.lower_limit > r.upper_limit + 1
) as missing_higher
from routes r
where not exists (select 1
from routes r2
where r.upper_limit + 1 between r2.lower_limit and r2.upper_limit
);