select 来自 table 的记录基于行比较逻辑但使用集合操作
select records from a table based on row comparison logic but using set operation
我知道这个问题听起来有点奇怪,但这是真的
我有一个 table 没有唯一字段的 [Id,PType,TNo]。以下是数据集:
insert into test.dbo.test_tsac values
(1, 'tf' , 2 ),
(2, 'pg' , 3 ),
(3, 'tf' , 1 ),
(3, 'pg' , 1 ),
(4, 'tf' , 5 ),
(4, 'LL' , 2 ),
(4, 'pg' , 1 ),
(5, 'pg' , 2 ),
(5, 'pg' , 4 )
要求如下:
1.For 一个Id,如果只有一条记录保留在结果集中(例如
(1, 'tf' , 2 ),
(2, 'pg' , 3 )
2.for 如果记录多于
则为 id
如果记录有 "tf" 和 "pg" 因为 pType 然后丢弃 "pg" 记录并保留 tf 记录(示例数据行 3 和 4),但是,如果有一种情况,对于 1 个 id,有 3 个或更多记录具有多个 "tf"(除 PG 之外的任何内容),那么我们需要根据 Tno(ASCENDING) 选择一个,排除带有 PG 的记录示例 ( 在这 3 个中,
(4, 'tf', 5),
(4, 'LL' , 2 ),
(4, 'pg' , 1 ),
我们将选择 4,'LL',2 因为 4,pg,1 被丢弃,我们需要从剩余中进行升序排序。
- 如果一个 id 存在 2 条 Ptype = PG 的记录,则选择其中任何一条,可能是升序。
所以上述数据集的输出将是:
(1, 'tf' , 2 ),
(2, 'pg' , 3 ),
(3, 'tf' , 1 ),
\\\\\\\\
\\\\\\\\
(4, 'LL' , 2 ),
\\\\\\\\
(5, 'pg' , 2 ),
\\\\\\\\
我非常感谢这个很棒的社区提供的所有帮助,我不希望这里有一个完整的 executable 查询。任何 idea/approach/suggestion 都有很大帮助
请注意,我将需要 运行 在非常大的数据集 (~1M) 上执行此操作,因此我认为使用 Cursor 是不可取的,因此在设置操作上请求一些东西 basis.But如果 cursor/loops 是最后的选择,我也会这样做
我尝试过自连接,根据 Ptype 分离 tables 然后重新编译它们...分组也没有帮助。
使用 CTE
和 ROW_NUMBER()
,有条件 ORDER BY
declare @test table (Id int, PType char(2), TNo int)
insert into @test
values
(1, 'tf' , 2 ),
(2, 'pg' , 3 ),
(3, 'tf' , 1 ),
(3, 'pg' , 1 ),
(4, 'tf' , 5 ),
(4, 'LL' , 2 ),
(4, 'pg' , 1 ),
(5, 'pg' , 2 ),
(5, 'pg' , 4 )
;with cte as(
select *,
RN = row_number() over (partition by Id order by case when PType = 'tf' then 1 end, PType, TNo)
from @test)
select
Id
,PType
,TNo
from
cte
where RN = 1
我知道这个问题听起来有点奇怪,但这是真的
我有一个 table 没有唯一字段的 [Id,PType,TNo]。以下是数据集:
insert into test.dbo.test_tsac values
(1, 'tf' , 2 ),
(2, 'pg' , 3 ),
(3, 'tf' , 1 ),
(3, 'pg' , 1 ),
(4, 'tf' , 5 ),
(4, 'LL' , 2 ),
(4, 'pg' , 1 ),
(5, 'pg' , 2 ),
(5, 'pg' , 4 )
要求如下:
1.For 一个Id,如果只有一条记录保留在结果集中(例如
(1, 'tf' , 2 ),
(2, 'pg' , 3 )
2.for 如果记录多于
则为 id如果记录有 "tf" 和 "pg" 因为 pType 然后丢弃 "pg" 记录并保留 tf 记录(示例数据行 3 和 4),但是,如果有一种情况,对于 1 个 id,有 3 个或更多记录具有多个 "tf"(除 PG 之外的任何内容),那么我们需要根据 Tno(ASCENDING) 选择一个,排除带有 PG 的记录示例 ( 在这 3 个中,
(4, 'tf', 5), (4, 'LL' , 2 ), (4, 'pg' , 1 ),
我们将选择 4,'LL',2 因为 4,pg,1 被丢弃,我们需要从剩余中进行升序排序。
- 如果一个 id 存在 2 条 Ptype = PG 的记录,则选择其中任何一条,可能是升序。
所以上述数据集的输出将是:
(1, 'tf' , 2 ),
(2, 'pg' , 3 ),
(3, 'tf' , 1 ),
\\\\\\\\
\\\\\\\\
(4, 'LL' , 2 ),
\\\\\\\\
(5, 'pg' , 2 ),
\\\\\\\\
我非常感谢这个很棒的社区提供的所有帮助,我不希望这里有一个完整的 executable 查询。任何 idea/approach/suggestion 都有很大帮助
请注意,我将需要 运行 在非常大的数据集 (~1M) 上执行此操作,因此我认为使用 Cursor 是不可取的,因此在设置操作上请求一些东西 basis.But如果 cursor/loops 是最后的选择,我也会这样做
我尝试过自连接,根据 Ptype 分离 tables 然后重新编译它们...分组也没有帮助。
使用 CTE
和 ROW_NUMBER()
,有条件 ORDER BY
declare @test table (Id int, PType char(2), TNo int)
insert into @test
values
(1, 'tf' , 2 ),
(2, 'pg' , 3 ),
(3, 'tf' , 1 ),
(3, 'pg' , 1 ),
(4, 'tf' , 5 ),
(4, 'LL' , 2 ),
(4, 'pg' , 1 ),
(5, 'pg' , 2 ),
(5, 'pg' , 4 )
;with cte as(
select *,
RN = row_number() over (partition by Id order by case when PType = 'tf' then 1 end, PType, TNo)
from @test)
select
Id
,PType
,TNo
from
cte
where RN = 1