SQL Server中的联合与联接

SQL Server中的联合与联接,sql,sql-server-2008,join,union,Sql,Sql Server 2008,Join,Union,我的SQL代码执行以下操作:它获取所有文本,其中O_Top-previous O_Top

我的SQL代码执行以下操作:它获取所有文本,其中O_Top-previous O_Top<30,O_Left-previous O_Left<100

表中的数据如下:

Text      O_Top        O_Left     
------------------------------
 D         536          654
 5         401          544
 1         392          581
 2         395          609
 K         418          666
 1         329          142
 K         421          711
 H         424          753
 9         228          1194
 5         205          666
SQL代码:

;WITH cte AS
(
    SELECT 
        [Text], [O_Top], [O_Left], 
        ID = ROW_NUMBER() OVER (ORDER BY [O_Left]) 
    FROM
        MyTableName
)
SELECT * 
FROM cte AS c1
LEFT JOIN CTE c2 ON c1.ID = C2.ID - 1
WHERE ABS(c1.O_Top - c2.O_Top) < 30 
  AND ABS(C1.O_Left - c2.O_Left) < 110
ORDER BY C1.[O_Left]
我期待do like UNION的结果如下:

Text    O_Top   O_Left  ID
---------------------------
5        401    544     2        
1        392    581     3        
K        418    666     7        
K        421    711     8        
1        392    581     3
2        395    609     4
K        421    711     8
H        424    753     9
我正在寻找一种避免重复列的方法,如果我能在同一个SQL命令中使用类似distinct的东西,那么我会非常惊讶,因为现在重复的ID是8和3

我试着想了很多,但我觉得命令太复杂了,我的大脑无法处理它


非常感谢您的帮助和支持

您可以通过对当前CTE的联合查询来实现所需。尝试此操作,请参见下面的说明:

WITH cte2 AS (
    SELECT
        c1.Text AS Text1, c1.O_Top AS O_Top1, c1.O_Left AS O_Left1, c1.ID AS ID1,
        c2.Text AS Text2, c2.O_Top AS O_Top2, c2.O_Left AS O_Left2, c2.ID AS ID2
    FROM cte AS c1
    LEFT JOIN cte c2
        ON c1.ID = c2.ID - 1
    WHERE ABS(c1.O_Top - c2.O_Top)   < 30  AND 
          ABS(c1.O_Left - c2.O_Left) < 110
),
cte3 AS (
    SELECT
        Text1 AS Text, O_Top1 AS O_Top, O_Left1 AS O_Left, ID1 AS ID, 1 AS pos
    FROM cte2
    UNION ALL
    SELECT
        Text2, O_Top2, O_Left2, ID2, 2
    FROM cte2
)

SELECT *
FROM cte3
ORDER BY
    pos,
    O_Left
为了实现这一点,我做了以下更改:

为原始CTE中的两组列使用显式别名 在cte3联合查询中添加了一个计算列,以跟踪正在选择的值集 使用上面的计算列从cte3中选择,以您想要的方式对记录进行排序
在查询中,您只需在cte之间的自连接条件上添加或c1.ID=C2.ID+1,然后仅从c1中选择。这样可以同时比较上一行和下一行。如果您希望获得独特的结果,请添加distinct

;With cte as
  (Select [Text],[O_Top],[O_Left], ID = Row_Number() over(order bY [O_Left]) 
    from MyTableName)

 Select distinct c1.* 
 from cte as c1
 left Join cte  c2
 on c1.ID = C2.ID - 1 OR c1.ID = C2.ID +1
 where ABS(c1.O_Top - c2.O_Top) < 30 
 and ABS(C1.O_Left - c2.O_Left) < 110
 order bY C1.[O_Left]

或者将两个or条件替换为ABSc1.ID-C2.ID=1

我看不到数据和查询之间的关系。但是,如果要取消打印结果,可以使用交叉应用:


非常感谢你,我正在尝试,我会告诉你:神奇是完美的:D,我能知道这个额外的字段pos是如何工作的吗?字段pos是一个计算列,我们添加它来跟踪记录的来源。您可以通过其工作方式查看外部顺序。旁注:您的示例值与结果表中的值不匹配。是的,您是对的。很抱歉,我现在会尝试编辑它谢谢你的添加,这是我第一次知道交叉申请
;With cte as
  (Select [Text],[O_Top],[O_Left], ID = Row_Number() over(order bY [O_Left]) 
    from MyTableName)

 Select distinct c1.* 
 from cte as c1
 left Join cte  c2
 on c1.ID = C2.ID - 1 OR c1.ID = C2.ID +1
 where ABS(c1.O_Top - c2.O_Top) < 30 
 and ABS(C1.O_Left - c2.O_Left) < 110
 order bY C1.[O_Left]
With cte as (
      Select [Text],[ O_Top], [O_Left],
             ID = Row_Number() over(order bY [O_Left]) 
      from MyTableName
     )
Select v.*
from cte c1 left join
     cte c2
     on c1.ID = C2.ID - 1 cross apply
     (values (c1.[Text], c1.O_Top, c1.O_Left, c1.id),
             (c2.[Text], c2.O_Top, c2.O_Left, c2.id)
     ) v([Text], O_Top, O_Left, id)
where ABS(c1.O_Top - c2.O_Top) < 30 and
      ABS(C1.O_Left - c2.O_Left) < 110;