Reputation: 51
I have my SQL code that is doing the following: it gets all the "Text" where (O_Top - previous O_Top) < 30 and (O_Left - previous O_Left) < 100
The data in the table:
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
The SQL code:
;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]
The result I get:
Text O_Top O_Left ID Text O_Top O_Left ID
-----------------------------------------------------------
5 401 544 2 1 392 581 3
1 392 581 3 2 395 609 4
K 418 666 7 K 421 711 8
K 421 711 8 H 424 753 9
I'm looking up to do like UNION
to have the result as follows:
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
I'm searching a way to avoid the repetition of the columns and will be really amazing if I can use something like distinct in same SQL command so will show me unique results as now is repeating ID's like 8 and 3
I try to think a lot about but I feel the command is that much complex that my brain can't handle it
Thanks a lot in advance for help and support!
Upvotes: 1
Views: 62
Reputation: 1269773
I don't see the relationship between your data and your query. But, if you want to unpivot your results, you can use cross apply
:
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;
Upvotes: 0
Reputation: 18559
In your query you can just add OR c1.ID = C2.ID +1
on a self join condition between the cte, and select just from c1. This way you would be comparing both previous and next row at the same time. Add distinct if you wish unique results.
;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 replace two OR
conditions with ABS(c1.ID - C2.ID) = 1
Upvotes: 0
Reputation: 521249
You can achieve what you want with a union query of your current CTE. Try this, and see below for an explanation:
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
To make this work, I made the following changes:
cte3
union query to keep track of which set of values are being selectedcte3
using the computed column above to order the records the way you wantUpvotes: 1