SQL 任意位置:查找与另一行相比 +-2 的行
SQL Anywhere: find rows that are +-2 compared to another row
我有以下 table:
ID User Form Depth
1 A ABC 2001
1 A XYZ 1001
1 B XYZ 1003
1 B DEF 3001
1 C XYZ 1000
如果 ID 和表单相同,我需要从用户 A 中识别出那些 +-2 的行。使用上面的示例,脚本将 return:
ID User Form Depth
1 B XYZ 1003
1 C XYZ 1000
我已经有一个脚本可以识别具有相同 ID 和表单的行——我只需要另一部分,但我正在努力弄清楚其中的逻辑。我希望有某种我可以使用的 DIFF 函数,但我找不到 SQL Anywhere.
有人有什么建议吗?
谢谢!
我想你想要 exists
:
select t.*
from t
where t.user <> 'A' and
exists (select 1
from t t2
where t2.form = t.form and t2.id = t.id and
t2.depth between t.depth - 2 and t.depth + 2
);
如果您要查找的深度恰好是 A 深度的 +/-2:
select t1.*
from mytab t1,
mytab t2
where t1.id = t2.id
and t1.form = t2.form
and t1.user != 'A'
and t2.user = 'A'
and abs(t1.depth - t2.depth) = 2
go
ID User Form Depth
--- ----- ----- -----
1 B XYZ 1003
如果您要查找的深度在 A 的深度的 2 以内(即 diff <= 2):
select t1.*
from mytab t1,
mytab t2
where t1.id = t2.id
and t1.form = t2.form
and t1.user != 'A'
and t2.user = 'A'
and abs(t1.depth - t2.depth) <= 2
go
ID User Form Depth
--- ----- ----- -----
1 B XYZ 1003
1 C XYZ 1000
这是非常基本的 SQL,所以虽然 fiddle 是用 MySQL 完成的,但您应该会发现查询在 SQLAnywhere 中也有效:sql fiddle
一种快速而肮脏的通用方法。
将 @User
替换为您想要删除的任何人。
DECLARE @table TABLE (
ID Int
,[User] VARCHAR(2)
,Form VARCHAR(3)
,Depth INT
)
DECLARE @User VARCHAR(2) = 'A'
INSERT INTO @table (ID , [User], Form, Depth)
VALUES
(1 , 'A' , 'ABC' , 2001),
(1 , 'A' , 'XYZ' , 1001),
(1 , 'B' , 'XYZ' , 1003),
(1 , 'B' , 'DEF' , 3001),
(1 , 'C' , 'XYZ' , 1000)
SELECT t1.ID, t1.[User], t1.Form, t1.Depth , ROW_NUMBER() OVER(ORDER BY t1.ID, t1.[User], t1.Form, t1.Depth) AS [row_number]
INTO #temp
FROM @table as t1
INNER JOIN (
SELECT t.ID, t.Form, COUNT('8') as [count]
FROM @table as t
GROUP BY ID, Form
HAVING COUNT('8') > 1
) as duplicates
ON duplicates.ID = t1.ID
AND duplicates. Form = t1.Form
ORDER BY ID, User, Form, Depth
-- SELECT * FROM #temp
SELECT [row_number] - 2 as value
INTO #range
FROM #temp as t
WHERE t.[User] = @User
--SELECT * FROM #range
INSERT INTO #range
SELECT [row_number] - 1
FROM #temp as t
WHERE t.[User] = @User
INSERT INTO #range
SELECT [row_number] + 1
FROM #temp as t
WHERE t.[User] = @User
INSERT INTO #range
SELECT [row_number] + 2
FROM #temp as t
WHERE t.[User] = @User
SELECT * FROM #temp
WHERE [row_number] IN (SELECT value FROM #range)
DROP TABLE #temp
DROP TABLE #range
我有以下 table:
ID User Form Depth
1 A ABC 2001
1 A XYZ 1001
1 B XYZ 1003
1 B DEF 3001
1 C XYZ 1000
如果 ID 和表单相同,我需要从用户 A 中识别出那些 +-2 的行。使用上面的示例,脚本将 return:
ID User Form Depth
1 B XYZ 1003
1 C XYZ 1000
我已经有一个脚本可以识别具有相同 ID 和表单的行——我只需要另一部分,但我正在努力弄清楚其中的逻辑。我希望有某种我可以使用的 DIFF 函数,但我找不到 SQL Anywhere.
有人有什么建议吗?
谢谢!
我想你想要 exists
:
select t.*
from t
where t.user <> 'A' and
exists (select 1
from t t2
where t2.form = t.form and t2.id = t.id and
t2.depth between t.depth - 2 and t.depth + 2
);
如果您要查找的深度恰好是 A 深度的 +/-2:
select t1.*
from mytab t1,
mytab t2
where t1.id = t2.id
and t1.form = t2.form
and t1.user != 'A'
and t2.user = 'A'
and abs(t1.depth - t2.depth) = 2
go
ID User Form Depth
--- ----- ----- -----
1 B XYZ 1003
如果您要查找的深度在 A 的深度的 2 以内(即 diff <= 2):
select t1.*
from mytab t1,
mytab t2
where t1.id = t2.id
and t1.form = t2.form
and t1.user != 'A'
and t2.user = 'A'
and abs(t1.depth - t2.depth) <= 2
go
ID User Form Depth
--- ----- ----- -----
1 B XYZ 1003
1 C XYZ 1000
这是非常基本的 SQL,所以虽然 fiddle 是用 MySQL 完成的,但您应该会发现查询在 SQLAnywhere 中也有效:sql fiddle
一种快速而肮脏的通用方法。
将 @User
替换为您想要删除的任何人。
DECLARE @table TABLE (
ID Int
,[User] VARCHAR(2)
,Form VARCHAR(3)
,Depth INT
)
DECLARE @User VARCHAR(2) = 'A'
INSERT INTO @table (ID , [User], Form, Depth)
VALUES
(1 , 'A' , 'ABC' , 2001),
(1 , 'A' , 'XYZ' , 1001),
(1 , 'B' , 'XYZ' , 1003),
(1 , 'B' , 'DEF' , 3001),
(1 , 'C' , 'XYZ' , 1000)
SELECT t1.ID, t1.[User], t1.Form, t1.Depth , ROW_NUMBER() OVER(ORDER BY t1.ID, t1.[User], t1.Form, t1.Depth) AS [row_number]
INTO #temp
FROM @table as t1
INNER JOIN (
SELECT t.ID, t.Form, COUNT('8') as [count]
FROM @table as t
GROUP BY ID, Form
HAVING COUNT('8') > 1
) as duplicates
ON duplicates.ID = t1.ID
AND duplicates. Form = t1.Form
ORDER BY ID, User, Form, Depth
-- SELECT * FROM #temp
SELECT [row_number] - 2 as value
INTO #range
FROM #temp as t
WHERE t.[User] = @User
--SELECT * FROM #range
INSERT INTO #range
SELECT [row_number] - 1
FROM #temp as t
WHERE t.[User] = @User
INSERT INTO #range
SELECT [row_number] + 1
FROM #temp as t
WHERE t.[User] = @User
INSERT INTO #range
SELECT [row_number] + 2
FROM #temp as t
WHERE t.[User] = @User
SELECT * FROM #temp
WHERE [row_number] IN (SELECT value FROM #range)
DROP TABLE #temp
DROP TABLE #range