在改变数字范围内找到缺失值

时间:2015-11-02 18:04:04

标签: sql tsql

我试图找到遗失或“跳过”'我表中的值。这是我的表的一个例子。

| Country      | U  | Date     |
| USA          | 1  | 1/1/2015 |
| USA          | 2  | 2/1/2015 |
| USA          | 3  | 3/1/2015 |
| USA          | 5  | 5/1/2015 |
| USA          | 6  | 6/1/2015 |
| USA          | 7  | 7/1/2015 |
| USA          | 8  | 8/1/2015 |
| USA          | 9  | 9/1/2015 |
| Germany      | 2  | 4/1/2015 |
| Germany      | 3  | 5/1/2015 |
| Germany      | 4  | 6/1/2015 |
| Germany      | 5  | 7/1/2015 |
| Germany      | 6  | 8/1/2015 |
| Germany      | 7  | 9/1/2015 |
| Canada       | 1  | 3/1/2015 |
| Canada       | 2  | 4/1/2015 |
| Canada       | 3  | 6/1/2015 |
| Canada       | 4  | 7/1/2015 |

我需要找到一些可能导致两个不同查询的事情,这是好的。

首先按国家/地区分组并按美国过滤时,您会发现U列从1-9开始,但缺少U = 4以及与该行于2015年4月1日对应的月份。

其次,当按国家/地区分组并按德国过滤时,您会发现U列缺少第一条记录,其中U = 1且其对应日期为3/1/2015。

然后最后按国家/地区分组并按加拿大过滤时,您会发现U列具有顺序排序,但是Date列缺少一个月 - 2015年5月1日。

我已经尝试了LAG()LEAD()方法,但这似乎不起作用,因为我无法汇总U。有没有人解决这个问题?

2 个答案:

答案 0 :(得分:0)

我认为您可以使用cte来构建数字和日期表,然后使用left join主表来查找丢失的记录。

with nums as (select 1 as num union all select 2 union all ... select 9)
, dates as (select '01/01/2015' as dt union all select '02/01/2015'..
            select '12/01/2015')
select n.num, t.country, d.dt
from nums n
left join tablename t on n.num = t.U
left join dates d on d.dt = t.date
where t.U is null or t.date is null

答案 1 :(得分:0)

您似乎只是想找到丢失的月份,U可以忽略,除非它以大于1的整数开头,在这种情况下您需要使用{{ 1}}查找UU开始时存在的缺失日期。

如果您需要在1中找到缺失的数字,则必须对其进行调整,因为它只关注缺少的日期。

鉴于数据:

U

您可以使用两个查询为每个国家/地区构建declare @data table (Country varchar(10), U int, [Date] date) insert into @data values ('USA', 1, '1/1/2015'), ('USA', 2, '2/1/2015'), ('USA', 3, '3/1/2015'), ('USA', 5, '5/1/2015'), ('USA', 6, '6/1/2015'), ('USA', 7, '7/1/2015'), ('USA', 8, '8/1/2015'), ('USA', 9, '9/1/2015'), ('Germany', 2, '4/1/2015'), ('Germany', 3, '5/1/2015'), ('Germany', 4, '6/1/2015'), ('Germany', 5, '7/1/2015'), ('Germany', 6, '8/1/2015'), ('Germany', 7, '9/1/2015'), ('Canada', 1, '3/1/2015'), ('Canada', 2, '4/1/2015'), ('Canada', 3, '6/1/2015'), ('Canada', 4, '7/1/2015') min日期列表,然后构建每个国家/地区应存在的完整日期列表。

max

如果我们检查select Country, dateadd(month, (-1 * min(U)) + 1, min([Date])) as min_Date, max([Date]) as max_Date into #min_max from @data group by Country ;with cte (Country, [Date]) as ( select Country, min_Date from #min_max union all select cte.Country, dateadd(month, 1, cte.Date) from #min_max t inner join cte on t.Country = cte.Country where cte.[Date] < t.max_Date ) select * into #ranges from cte #min_max中的数据,您会看到以下内容:

#ranges

然后在select * from #min_max Country min_Date max_Date ---------- ---------- ---------- Canada 2015-03-01 2015-07-01 Germany 2015-03-01 2015-09-01 USA 2015-01-01 2015-09-01 select * from #ranges order by 1, 2 Country Date ---------- ---------- Canada 2015-03-01 Canada 2015-04-01 Canada 2015-05-01 Canada 2015-06-01 Canada 2015-07-01 Germany 2015-03-01 Germany 2015-04-01 Germany 2015-05-01 Germany 2015-06-01 Germany 2015-07-01 Germany 2015-08-01 Germany 2015-09-01 USA 2015-01-01 USA 2015-02-01 USA 2015-03-01 USA 2015-04-01 USA 2015-05-01 USA 2015-06-01 USA 2015-07-01 USA 2015-08-01 USA 2015-09-01 中找到原始数据中不存在的记录很简单:

#ranges

然后我们放下临时表:

select *
from   #ranges r
where  not exists (
         select 1
         from   @data d
         where  r.Country = d.Country
           and  r.[Date] = d.[Date]
       )

Country    Date
---------- ----------
Germany    2015-03-01
USA        2015-04-01
Canada     2015-05-01