1

使用 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

现在我想排除除给定代码之外的任何 G=1 (在同一结果集中)的行的 L 介于 L 和 R 之间的行(基本上对除给定代码之外的所有 G=1 执行“L 和 R 之间”) , 同时仍然保持所有 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
4

2 回答 2

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
于 2013-09-17T23:51:51.923 回答
0

使用您规定的标准:

排除 G=1(在同一结果集中)的任何行的 L 介于 L 和 R 之间的行,除了给定的代码(基本上对除给定的代码之外的所有 G=1 执行“L 和 R 之间的 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'))

但是,您的预期结果似乎与您声明的标准不符。您似乎在说(对于此数据集和标准)您要排除介于 229 ( where ) 和 610 ( where ) 之间的G<>1行,但这些行似乎与您声明的标准的明显意图不匹配:LMIN(L)Code <> '020286'MAX(R)Code <> '020286'

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

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

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

WITH Criteria
AS (SELECT Code, L, R, G
    FROM @t
    WHERE G = 1)
SELECT T.Code, T.L, T.R, T.G
FROM @t AS T
INNER JOIN Criteria
    ON T.L >= Criteria.L 
         AND T.L <= Criteria.R 
         AND T.G <> 1 
         AND Criteria.Code <> '020286'
UNION ALL
SELECT Code, L, R, G
FROM Criteria
ORDER BY 1
于 2013-09-18T00:27:46.910 回答