2012-07-04 3 views
6

Ich verwende SQL Server 2008 R2.Wie für eine Reihe von gleichen X gepaarten Zeilen in einer Zeile auf eine bestimmte Spalte zu testen?

Betrachten Sie diese Tabelle @t (TOP 20 von ORDER BY PK DESC):

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 

mit diesem Erstellt:

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) 

ist Meine Aufgabe true für ein Spiel, wenn die letzte Zeile zurückzukehren (where APP IS NOT NULL) vervollständigen eine Reihe von passenden Paaren X oder letzte Zeilen der gleichen Gruppe (gleicher Strom SK).

Wenn zum Beispiel nur 2 Paare testen, angesichts der aktuellen erforderlichen Test wird auf SK = 6 ist, sobald zu bekommen PK = 19 eine Übereinstimmung vorhanden ist.

Das Spiel VC ist (19) = VC (11) = 79 und VC (17) = VC (7) = 74

sehen, dass die durch das Ausführen folgender:

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 

Ergebnisse:

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 

ein weiteres Beispiel:

wenn für 3 Paare testen, eine Übereinstimmung auf PK = 20 bei der Suche in SK = 9gefunden wird(Obwohl es eine interessante Frage ist, für meine Aufgabe gibt es keine Notwendigkeit, für alle SKs zu testen. Ein Ergebnis für einen gegebenen SK ist ausreichend für mich.

Um zu sehen, das Spiel dies auszuführen:

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 

die Ergebnisse:

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 

wie Sie sehen können: VC (20) = VC (14) = 74, VC (18) = VC (13) = 74 und VC (15) = VC (2)

Ich dachte über die Auswahl der erforderlichen Sätze von Zeilen in der richtigen Reihenfolge und zählen die gleichen Zeilen in VC. Wenn die Zählung die gleiche wie die @PairsToTest ist, ist dies das Zeichen, um eine Flagge zu heben.

Ich habe versucht:

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 

aber es gibt zu may Fehler in dieser:

  1. VC keine eindeutigen Daten (nur zufällig) enthalten
  2. die IF nicht
  3. erlaubt ist
  4. ich soll die TOP 99999999 in t3 loszuwerden (obwohl ich damit leben kann)

Was sind die erforderlichen Änderungen, die ich ergreifen sollte, um dies zu lösen?

+2

Du hast mir nur Kopfschmerzen ... – Jim

Antwort

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

diesen Code versuchen, es zählt Anzahl von Zeilenpaaren in jedem der SK-Partitionen und schließt Zeilen ohne ein Paar aus dem Ergebnis:

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 
Verwandte Themen