我有一张表:
id
number
year
我想找到"漏洞"或差距,不考虑id,而只考虑几年/数字。
当同一年有两个非连续数字时,有一个缺口,结果是年份和两个非连续数字之间的所有数字(不包括极值)。另请注意,下端始终为1 ,因此如果缺少1,则为间隙。
例如,拥有:
id n year
1 1 2012
2 2 2012
3 5 2012
4 2 2010
我想要结果:
3/2012
4/2012
1/2010
答案 0 :(得分:3)
在序列中查找缺失条目的技巧是生成序列中所有可用组合的笛卡尔积,然后使用NOT EXISTS
来消除存在的那些。这在非DBMS特定方式中很难做到,因为它们都有不同的方式可以在运行中选择性地创建序列。对于Oracle,我使用:
SELECT RowNum AS r
FROM Dual
CONNECT BY Level <= MaxRequiredValue;
因此,要生成所有可用年/ n对的列表,我将使用:
SELECT d.Year, n.r
FROM ( SELECT year, MAX(n) AS MaxN
FROM T
GROUP BY Year
) d
INNER JOIN
( SELECT RowNum AS r
FROM Dual
CONNECT BY Level <= (SELECT MAX(n) FROM T)
) n
ON r < MaxN;
我获得每年的最大n并将其连接到从1到最高n的整数列表,其中此整数列出的最高值小于该年的最大值。
最后使用NOT EXISTS
来消除已存在的值:
SELECT d.Year, n.r
FROM ( SELECT year, MAX(n) AS MaxN
FROM T
GROUP BY Year
) d
INNER JOIN
( SELECT RowNum AS r
FROM Dual
CONNECT BY Level < (SELECT MAX(n) FROM T)
) n
ON r = MaxN
WHERE NOT EXISTS
( SELECT 1
FROM T
WHERE d.Year = t.Year
AND n.r = t.n
);
上的工作示例
修改强>
由于我找不到非DMBS特定的解决方案,我认为我最好做一些体面的事情并为其他DBMS创建一些示例。
答案 1 :(得分:0)
另一种选择是使用像这样的临时表:
create table #tempTable ([year] int, n int)
insert
into #tempTable
select t.year, 1
from tableName t
group by t.year
while exists(
select *
from tableName t1
where t1.n > (select MAX(t2.n) from #tempTable t2 where t2.year = t1.year)
)
begin
insert
into #tempTable
select t1.year,
(select MAX(t2.n)+1 from #tempTable t2 where t2.year = t1.year)
from tableName t1
where t1.n > (select MAX(t2.n) from #tempTable t2 where t2.year = t1.year)
end
delete t2
from #tempTable t2
inner join tableName t1
on t1.year = t2.year
and t1.n = t2.n
select [year], n
from #tempTable
drop table #tempTable