使用该结果集中的条件从结果集中排除组

时间:2013-09-17 23:06:00

标签: sql tsql

使用SQL Server 2008。

我们获得了一个代码,比如020286,它给了我们一个起始结果集。 开始数据:

Code    L   R   G
020286  2   703 1
030383  3   6   0
031847  4   5   0
021932  7   10  0
022499  8   9   0
020068  229 310 1
020866  231 306 1
020524  232 241 0
030772  233 234 0
031787  235 236 0
031859  237 238 0
031947  239 240 0
020964  242 323 1
021215  253 342 1
030728  343 344 0
020990  345 346 0
022521  347 354 0

现在我想排除L在L和R之间的行,其中G = 1(在同一结果集中)除了给定代码的任何行之外(对于所有G = 1,基本上做“L和L之间的L”除了给定代码),同时仍然保持所有G = 1。 预期结果:

Code    L   R   G
020286  2   703 1
030383  3   6   0
031847  4   5   0
021932  7   10  0
022499  8   9   0
020068  229 310 1
020866  231 306 1
020964  242 323 1
021215  253 342 1
030728  343 344 0
020990  345 346 0
022521  347 354 0

这是一个包含起始数据的表格变量。

declare @t table (Code nvarchar(10),L int, R int, G int)
insert into @t (Code, L, R, G)
select '020286',2,703,1 union
select '030383',3,6,0 union
select '031847',4,5,0 union
select '021932',7,10,0 union
select '022499',8,9,0 union
select '020068',229,610,1 union
select '020866',231,396,1 union
select '020524',232,241,0 union
select '030772',233,234,0 union
select '031787',235,236,0 union
select '031859',237,238,0 union
select '031947',239,240,0 union
select '020964',242,383,1 union
select '021215',253,342,1 union
select '030728',343,344,0 union
select '020990',345,346,0 union
select '022521',347,354,0

select * from @t

2 个答案:

答案 0 :(得分:1)

据推测,给定的代码在某种程度上是可识别的,所以我假设有一个包含它的变量,我正在调用@given:

DECLARE @given nvarchar(10)
SELECT @given = '020286'

首先确定G = 1且不是给定代码的行的L:

SELECT L INTO #L FROM @t WHERE G=1 AND Code <> @given;

现在我们需要将#L中的每对连续值连接到一个新表中的行中,然后可以使用它来计算我们不想要的@t中的哪些行。有几种方法可以做到这一点,但这个方法非常简单易懂:

SELECT L as [Low], Cast(0 as int) as [High] 
INTO #Pairs 
FROM #L 
WHERE L < (SELECT Max(L) FROM #L);

UPDATE #Pairs SET [High] = (SELECT Min(L) FROM #L WHERE L > [Low]);

现在删除@t中不需要的行:

DELETE t
FROM @t t CROSS JOIN #Pairs p
WHERE L > p.[Low] AND L < p.[High]

剩下的应该是正确的:

SELECT * FROM @t ORDER BY L

答案 1 :(得分:0)

使用您陈述的标准:

  

排除L在L和R之间的行,其中G = 1(在同一结果集中)除了给定代码之外的任何行(对于除了给定代码之外的所有G = 1,基本上做“L和L之间的L”),同时仍然保持所有G = 1:

SELECT * 
FROM @t 
WHERE G = 1 
      OR NOT(L >= (SELECT MIN(L) FROM @t WHERE G = 1 AND NOT Code = '020286') 
             AND L <= (SELECT MAX(R) FROM @t WHERE G = 1 AND NOT Code = '020286'))

但是,您的预期结果似乎与您声明的标准不符。您似乎在说(对于此数据集和条件)您想要在{22}(G<>1其中L)和610({{}之间排除MIN(L)Code <> '020286'的行1}} MAX(R)},但这些行似乎与您所述标准的明显意图相符:

Code <> '020286'

事实上,您的标准似乎实际上是:

  

排除L在L和R之间的行,其中G = 1(在同一结果集中)除了给定代码之外的任何之前行(对于前一个 G = 1,除了给定的代码),同时仍然保持所有G = 1:

CODE    L   R   G
030728  343 344 0
020990  345 346 0
022521  347 354 0