首先从2列中未使用

时间:2014-03-20 14:51:54

标签: sql-server tsql

我必须在每一列中找到第一个匹配,在一行tsql中需要(没有循环或游标 - 在光标回答后添加 - )

;WITH TempTable AS
(
    SELECT * FROM (VALUES (1,1),(2,2),(2,3),(3,2),(3,3),
                          (4,2),(4,3),(5,4)) AS y(pos,MatchingPos)
)
SELECT * FROM TempTable...

结果:

  1,1 returned
  2,2 returned
  2,3 Not returned: Column 1 Value 2 already returned
  3,2 Not returned: Column 2 Value 2 already returned
  3,3 returned
  4,2 Not returned: Column 2 Value 2 already returned
  4,3 Not returned: Column 2 Value 3 already returned
  5,4 returned

2 个答案:

答案 0 :(得分:0)

我不是游标的忠实粉丝。但这似乎是必要的:

Declare @t table(pos int,MatchingPos int)

Declare @pos int, @MatchingPos int
Declare SqlCursor CURSOR FAST_FORWARD FOR
SELECT pos,MatchingPos FROM 
(VALUES (1,1),(2,2),(2,3),(3,2),(3,3),
                          (4,2),(4,3),(5,4)) AS y(pos,MatchingPos)
OPEN SqlCursor
FETCH NEXT FROM SqlCursor
INTO @pos, @MatchingPos
WHILE @@FETCH_STATUS = 0
BEGIN

insert @t
select @pos, @MatchingPos
where not exists
(select 1 from @t where pos = @pos or @MatchingPos = MatchingPos)
     FETCH NEXT FROM SqlCursor
     INTO @pos, @MatchingPos
END
CLOSE SqlCursor
DEALLOCATE SqlCursor


select * from @t

结果:

pos MatchingPos
1   1
2   2
3   3
5   4

答案 1 :(得分:0)

好吧 - 这个CTE似乎适用于上面的数据集。它有点乱,CTE可以根据你的数据合理地轻松地进行最大递归。

;WITH TempTable AS
(
    SELECT * FROM (VALUES (1,1),(2,2),(2,3),(3,2),(3,3),
                          (4,2),(4,3),(5,4)) AS y(pos,MatchingPos)
), TempTable2 AS
(
    SELECT T1.pos, 
           T1.MatchingPos,
           CASE WHEN min(T2.MatchingPos) < T1.MatchingPos THEN 1 ELSE 0 END as Pos_Exists,
           CASE WHEN min(T3.pos) < T1.pos THEN 1 ELSE 0 END as MatchingPos_Exists,
           ROW_NUMBER() OVER(ORDER BY T1.pos ASC, T1.MatchingPos ASC) RowNum
    FROM TempTable T1
    LEFT JOIN TempTable T2
      ON T1.pos = T2.pos AND T1.MatchingPos != T2.MatchingPos
    LEFT JOIN TempTable T3
      ON T1.MatchingPos = T3.MatchingPos AND T1.pos != T3.pos
    GROUP BY T1.pos, T1.MatchingPos
)
, TempTable3 AS
(
    SELECT pos, MatchingPos, RowNum, 1 AS Included, CAST(0 aS BIGINT) ParentRow
    FROM TempTable2 
    WHERE  Pos_Exists = 0 AND MatchingPos_Exists = 0
    UNION ALL
    SELECT T1.pos, T1.MatchingPos, T1.RowNum,
        T2.Included - 1 AS Included, 
        CASE WHEN T2.Included = 1 THEN T2.RowNum WHEN T2.Included < 0 THEN T2.RowNum ELSE -1 END as ParentRow
    FROM TempTable2 T1
    JOIN TempTable3 T2
    ON T1.RowNum > T2.RowNum 
      AND (T1.pos = T2.pos OR T1.MatchingPos = T2.MatchingPos)
      AND (T2.ParentRow != 0 OR T2.Included = 1)
)

SELECT pos, MatchingPos FROM TempTable3 
GROUP BY pos, MatchingPos
HAVING MAX(Included) = 1 OR (MAX(ParentRow) = -1)