2012-07-04 24 views
6

Tôi đang sử dụng SQL Server 2008 R2.Làm cách nào để kiểm tra một chuỗi các hàng được ghép đôi X bằng một hàng đề cập đến một cột cụ thể?

Cân nhắc @t bảng này (TOP 20 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 

Created với điều này:

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) 

Nhiệm vụ của tôi là để trở true cho một trận đấu nếu hàng mới nhất (where APP IS NOT NULL) hoàn thành một loạt các cặp phù hợp X hoặc các hàng mới nhất của cùng một nhóm (cùng một SK hiện tại).

Ví dụ: khi thử nghiệm chỉ 2 cặp, cho thử nghiệm bắt buộc hiện tại là trên SK = 6, ngay khi nhận được PK = 19, có một kết quả phù hợp.

Trận đấu là VC (19) = VC (11) = 79 VÀ VC (17) = VC (7) = 74

Thấy rằng bằng cách thực hiện như sau:

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 

kết quả:

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 

một ví dụ khác:

khi thử nghiệm cho 3 cặp, một trận đấu được tìm thấy trên PK = 20 khi nhìn ở SK = 9 (Mặc dù nó là câu hỏi thú vị của chính nó, cho nhiệm vụ của tôi không cần phải kiểm tra cho tất cả các SK. Một kết quả cho một SK nhất định là đủ cho tôi.

Để xem trận đấu thực hiện điều này:

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 

mà kết quả:

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 

như bạn có thể thấy: VC (20) = VC (14) = 74, VC (18) = VC (13) = 74 và VC (15) = VC (2)

Tôi đã nghĩ chọn các bộ hàng yêu cầu theo đúng thứ tự và đếm các hàng bằng nhau trong VC. Nếu số đếm giống như số @PairsToTest thì đây là dấu hiệu để tăng cờ.

tôi đã cố gắng:

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 

nhưng có những sai sót quá may trong này:

  1. VC không chứa dữ liệu duy nhất (chỉ một cách tình cờ)
  2. IF không được phép
  3. Tôi nên loại bỏ TOP 99999999 bằng t3 (mặc dù tôi có thể sống với điều đó)

Những thay đổi cần thiết mà tôi nên thực hiện để giải quyết vấn đề này là gì?

+2

Bạn chỉ cần đưa cho tôi đau đầu ... – Jim

Trả lời

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

Hãy thử mã này, nó đếm số lượng các cặp hàng trong mỗi phân vùng SK và loại trừ hàng mà không có một cặp từ kết quả:

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