2012-07-04 10 views
6

Estoy usando SQL Server 2008 R2.¿Cómo se prueba una serie de filas emparejadas igual X en una fila que hace referencia a una columna específica?

Considere esto @t mesa (TOP 20 de ORDER BY DESC PK):

PK SK VC APP  M C 
== == == ==== == ================== 
21 7 79 NULL 0 NULL 
20 9 74 1  3 20=14, 18=13, 15=2 
19 6 79 1  2 19=11, 17=7 
18 9 77 1  0 NULL 
17 6 74 1  0 NULL 
16 7 79 1  0 NULL 
15 9 74 1  0 NULL 
14 9 74 1  0 NULL 
13 9 77 1  0 NULL 
12 7 77 1  0 NULL 
11 6 79 1  0 NULL 
10 7 79 1  0 NULL 
9 7 74 1  0 NULL 
8 7 79 1  0 NULL 
7 6 74 1  0 NULL 
6 6 74 1  0 NULL 
5 7 79 1  0 NULL 
4 7 77 1  0 NULL 
3 6 79 1  0 NULL 
2 9 74 1  0 NULL 

Creado con esto:

DECLARE @t TABLE(PK INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED, SK INT NOT NULL, VC INT NULL, APP INT NULL, M INT NOT NULL, C NVARCHAR(111) NULL); 

INSERT @t (SK,VC,APP,M,C) VALUES 
(7,77,1,0,NULL), 
(9,74,1,0,NULL), 
(6,79,1,0,NULL), 
(7,77,1,0,NULL), 
(7,79,1,0,NULL), 
(6,74,1,0,NULL), 
(6,74,1,0,NULL), 
(7,79,1,0,NULL), 
(7,74,1,0,NULL), 
(7,79,1,0,NULL), 
(6,79,1,0,NULL), 
(7,77,1,0,NULL), 
(9,77,1,0,NULL), 
(9,74,1,0,NULL), 
(9,74,1,0,NULL), 
(7,79,1,0,NULL), 
(6,74,1,0,NULL), 
(9,77,1,0,NULL), 
(6,79,1,2,'19=11, 17=7'), 
(9,74,1,3,'20=14, 18=13, 15=2'), 
(7,79,NULL,0,NULL) 

Mi tarea es devolver true para un partido si la última fila (where APP IS NOT NULL) complete una serie de pares coincidentes X o las últimas filas del mismo grupo (el mismo SK actual).

Por ejemplo, cuando se prueban solo 2 pares, dado que la prueba actual requerida es en SK = 6, tan pronto como llegue a PK = 19 hay una coincidencia.

El partido es VC (19) = VC (11) = 79 y VC (17) = VC (7) = 74

Ver que ejecutando el siguiente:

DECLARE @PairsToTest int = 2 
DECLARE @SK int = 6 
SELECT 
    TOP (2*@PairsToTest) 
    * 
    FROM @t 
    WHERE 
      APP IS NOT NULL 
     AND SK = @SK 
    ORDER BY SK, PK DESC 

resultados:

PK SK VC APP M C 
19 6 79 1 2 19=11, 17=7 
17 6 74 1 0 NULL 
11 6 79 1 0 NULL 
7 6 74 1 0 NULL 

Otro ejemplo:

cuando se prueba por 3 pares, se encuentra una coincidencia en PK = 20 cuando se mira en SK = 9 (Aunque es una pregunta interesante en sí misma, para mi tarea no es necesario probar todas las SK. Un resultado para un SK dado es suficiente para mí.

para ver el partido de ejecutar esta:

DECLARE @PairsToTest int = 3 
DECLARE @SK int = 9 
SELECT 
    TOP (2*@PairsToTest) 
    * 
    FROM @t 
    WHERE 
      APP IS NOT NULL 
     AND SK = @SK 
    ORDER BY SK, PK DESC 

que da como resultado:

PK SK VC APP M C 
20 9 74 1 3 20=14, 18=13, 15=2 
18 9 77 1 0 NULL 
15 9 74 1 0 NULL 
14 9 74 1 0 NULL 
13 9 77 1 0 NULL 
2 9 74 1 0 NULL 

como se puede ver: VC (20) = VC (14) = 74, VC (18) = VC (13) = 74 y VC (15) = VC (2)

Pensé en seleccionar los conjuntos de filas requeridos en el orden correcto, y contar las filas iguales en VC. Si el recuento es el mismo que el @PairsToTest, este es el letrero para levantar una bandera.

me trataron:

DECLARE @PairsToTest int = 3 
DECLARE @SK int = 9 
;with t0 as 
(
SELECT 
    TOP (2*@PairsToTest) 
    * 
    FROM @t 
    WHERE 
      APP IS NOT NULL 
     AND SK = @SK 
    ORDER BY SK, PK DESC 
), 
t1 AS 
(
SELECT TOP (@PairsToTest) * FROM t0 
), 
t2 AS 
(
SELECT TOP (@PairsToTest) * FROM t0 ORDER BY PK ASC 
) 
,t3 AS 
(
SELECT TOP 99999999 * FROM t2 ORDER BY PK DESC 
) 

IF (SELECT COUNT(*) FROM t1 LEFT OUTER JOIN t3 ON t1.VC = t3.VC) = @PairsToTest 
    SELECT 1 
ELSE 
    SELECT 0 

pero hay defectos demasiado mayo en esto:

  1. VC no contiene datos únicos (por casualidad)
  2. la SI no está permitido
  3. Debería deshacerme del TOP 99999999 en t3 (aunque puedo vivir con eso)

¿Cuáles son los cambios necesarios que debo realizar para resolver esto?

+2

Sólo me dio un dolor de cabeza ... – Jim

Respuesta

1
DECLARE @t TABLE(PK INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED, SK INT NOT NULL, VC INT NULL, APP INT NULL, M INT NOT NULL, C NVARCHAR(111) NULL); 

INSERT @t (SK,VC,APP,M,C) VALUES 
(7,77,1,0,NULL), 
(9,74,1,0,NULL), 
(6,79,1,0,NULL), 
(7,77,1,0,NULL), 
(7,79,1,0,NULL), 
(6,74,1,0,NULL), 
(6,74,1,0,NULL), 
(7,79,1,0,NULL), 
(7,74,1,0,NULL), 
(7,79,1,0,NULL), 
(6,79,1,0,NULL), 
(7,77,1,0,NULL), 
(9,77,1,0,NULL), 
(9,74,1,0,NULL), 
(9,74,1,0,NULL), 
(7,79,1,0,NULL), 
(6,74,1,0,NULL), 
(9,77,1,0,NULL), 
(6,79,1,2,'19=11, 17=7'), 
(9,74,1,3,'20=14, 18=13, 15=2'), 
(7,79,NULL,0,NULL) 


DECLARE @PairsToTest int = 3 
DECLARE @SK int = 9 

IF ((SELECT COUNT(*) FROM @t WHERE APP IS NOT NULL AND SK = @SK)[email protected]) >=0 
    BEGIN 
     DECLARE @swapData TABLE(PK1 INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED, PK INT NOT NULL, SK INT NOT NULL, VC INT NULL, APP INT NULL, M INT NOT NULL, C NVARCHAR(111) NULL); 
     DECLARE @olderData TABLE(PK2 INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED, PK INT NOT NULL, SK INT NOT NULL, VC2 INT NULL, APP INT NULL, M INT NOT NULL, C NVARCHAR(111) NULL); 
     DECLARE @newerData TABLE(PK3 INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED, PK INT NOT NULL, SK INT NOT NULL, VC3 INT NULL, APP INT NULL, M INT NOT NULL, C NVARCHAR(111) NULL); 


     INSERT @swapData SELECT TOP ((SELECT COUNT(*) FROM @t WHERE APP IS NOT NULL AND SK = @SK)[email protected]) * FROM @t WHERE APP IS NOT NULL AND SK = @SK ORDER BY PK 
     INSERT @olderData SELECT TOP (@PairsToTest) PK,SK,VC,APP,M,C FROM @swapData ORDER BY PK1 DESC 
     INSERT @newerData SELECT TOP (@PairsToTest) * FROM @t WHERE APP IS NOT NULL AND SK = @SK ORDER BY SK, PK DESC 



     DECLARE @Matches int = (SELECT COUNT(*)FROM @newerData INNER JOIN @olderData ON PK2 = PK3 WHERE VC2=VC3) 

     IF @Matches = @PairsToTest 
      SELECT 1 AS Match 
     ELSE 
      SELECT 0 AS Match 
    END 
ELSE 
    SELECT 0 AS Match 

/* 
SELECT TOP (2*@PairsToTest) * FROM @t WHERE APP IS NOT NULL AND SK = @SK ORDER BY SK, PK DESC 
SELECT * FROM @olderData 
SELECT * FROM @newerData 
*/ 
1

probar este código, se cuenta el número de pares de filas en cada una de las particiones SK y excluye filas sin un par del resultado:

DECLARE @t TABLE(PK INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED, SK INT NOT NULL, VC INT NULL, APP INT NULL, M INT NOT NULL, C NVARCHAR(111) NULL); 

INSERT @t (SK,VC,APP,M,C) VALUES 
(7,77,1,0,NULL), 
(9,74,1,0,NULL), 
(6,79,1,0,NULL), 
(7,77,1,0,NULL), 
(7,79,1,0,NULL), 
(6,74,1,0,NULL), 
(6,74,1,0,NULL), 
(7,79,1,0,NULL), 
(7,79,1,0,NULL), 
(6,79,1,0,NULL), 
(7,77,1,0,NULL), 
(9,77,1,0,NULL), 
(9,74,1,0,NULL), 
(9,74,1,0,NULL), 
(7,79,1,0,NULL), 
(6,74,1,0,NULL), 
(9,77,1,0,NULL), 
(6,79,1,2,'19=11, 17=7'), 
(9,74,1,3,'20=14, 18=13, 15=2'), 
(7,79,NULL,0,NULL) 

;WITH c AS 
(
    SELECT *, 
      DENSE_RANK() OVER (PARTITION BY SK ORDER BY VC DESC) DenseRankPartitionBySK, 
      ROW_NUMBER() OVER (PARTITION BY SK ORDER BY PK DESC) ordinalNumberInSKPartition 
    FROM @t 
    WHERE APP IS NOT NULL 
), 
e AS 
(
    SELECT *, 
      COUNT(*) OVER (PARTITION BY SK, DenseRankPartitionBySK) _Sum, 
      ROW_NUMBER() OVER (PARTITION BY SK, DenseRankPartitionBySK ORDER BY PK) Odd 
    FROM c 
), 
d AS (
    SELECT *, 
      COUNT(*) OVER (PARTITION BY SK) numberOfRows 
    FROM e 
    WHERE _Sum % 2 = 0 OR Odd <> 1 
) 

SELECT 
     d.PK, d.SK, d.VC, d.APP, d.M, d.C, 
     CASE WHEN ordinalNumberInSKPartition = 1 THEN 1 ELSE 0 END IsTopRow, 
     numberOfRows/2 [NumberOfPairsInSKPartition(M)] 
FROM d 
ORDER BY SK, PK DESC 
Cuestiones relacionadas