SQL/Teradata: Return 条连续行值相同的记录
SQL/Teradata: Return records where value in consecutive rows is the same
我的数据集如下所示:
ID date emp_num loc
1111 5/2/16 111111 Brooklyn
1112 5/3/16 222222 Detroit
1113 5/3/16 333333 San Diego
1114 5/2/16 333333 Orlando
1115 5/5/16 333333 Brooklyn
1116 5/7/16 111111 Orlando
在这种情况下,我想 return 记录 1113、1114 和 1115,因为连续行(按 ID 排序)中的 emp_num 是相同的。
我使用 Teradata,但如果有人有其他引擎的 SQL 解决方案,我通常可以设法翻译它。
谢谢。
首先,获取按 id 列排序并按 emp_num 分区并按 id 列排序的行号差异。这会将 emp_num 分类。然后,获取其中有多个成员的组(这意味着有连续的行具有相同的 emp_num 值)。最后 select 这些组所需的列。
WITH x AS (SELECT
*,
ROW_NUMBER() OVER (ORDER BY id) - ROW_NUMBER() OVER (PARTITION BY emp_num ORDER BY id) grp
FROM t),
grpsneeded
AS (SELECT
grp
FROM x
GROUP BY grp
HAVING COUNT(*) > 1)
SELECT
id,
dt,
emp_num
FROM x
WHERE grp IN (SELECT
grp
FROM grpsneeded)
此解决方案适用于 SQL 服务器。
更简单的 SQL 解决方案是使用 lead
和 lag
函数。正如@dnoeth 所指出的,Teradata 不支持这些功能。但是,这可能对其他数据库引擎有用。
select id, dt , emp_num from (
select *
,lead(emp_num) over(order by id) nxt
,lag(emp_num) over(order by id) prev
from t
) x
where coalesce(nxt,0) = emp_num or coalesce(prev,0) = emp_num
您需要查看 previous/next 行并检查它是否未更改:
SELECT *
FROM tab
QUALIFY
MIN(emp_num) --previous row
OVER (ORDER BY ID
ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) = emp_num
OR
MIN(emp_num) -- next row
OVER (ORDER BY ID
ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING) = emp_num
在标准 SQL 中,这将是 LAG
/LEAD
的任务,但 Teradata 不会阻止它,因此您必须重写它。
我的数据集如下所示:
ID date emp_num loc
1111 5/2/16 111111 Brooklyn
1112 5/3/16 222222 Detroit
1113 5/3/16 333333 San Diego
1114 5/2/16 333333 Orlando
1115 5/5/16 333333 Brooklyn
1116 5/7/16 111111 Orlando
在这种情况下,我想 return 记录 1113、1114 和 1115,因为连续行(按 ID 排序)中的 emp_num 是相同的。
我使用 Teradata,但如果有人有其他引擎的 SQL 解决方案,我通常可以设法翻译它。
谢谢。
首先,获取按 id 列排序并按 emp_num 分区并按 id 列排序的行号差异。这会将 emp_num 分类。然后,获取其中有多个成员的组(这意味着有连续的行具有相同的 emp_num 值)。最后 select 这些组所需的列。
WITH x AS (SELECT
*,
ROW_NUMBER() OVER (ORDER BY id) - ROW_NUMBER() OVER (PARTITION BY emp_num ORDER BY id) grp
FROM t),
grpsneeded
AS (SELECT
grp
FROM x
GROUP BY grp
HAVING COUNT(*) > 1)
SELECT
id,
dt,
emp_num
FROM x
WHERE grp IN (SELECT
grp
FROM grpsneeded)
此解决方案适用于 SQL 服务器。
更简单的 SQL 解决方案是使用 lead
和 lag
函数。正如@dnoeth 所指出的,Teradata 不支持这些功能。但是,这可能对其他数据库引擎有用。
select id, dt , emp_num from (
select *
,lead(emp_num) over(order by id) nxt
,lag(emp_num) over(order by id) prev
from t
) x
where coalesce(nxt,0) = emp_num or coalesce(prev,0) = emp_num
您需要查看 previous/next 行并检查它是否未更改:
SELECT *
FROM tab
QUALIFY
MIN(emp_num) --previous row
OVER (ORDER BY ID
ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) = emp_num
OR
MIN(emp_num) -- next row
OVER (ORDER BY ID
ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING) = emp_num
在标准 SQL 中,这将是 LAG
/LEAD
的任务,但 Teradata 不会阻止它,因此您必须重写它。