使用 DENSE_RANK 拆分数据集

Posted

技术标签:

【中文标题】使用 DENSE_RANK 拆分数据集【英文标题】:Using DENSE_RANK to split up a data set 【发布时间】:2014-05-07 13:23:04 【问题描述】:

我正在尝试使用以下内容拆分数据集,以便我可以根据另一个表中的值分配一个值。

这是迄今为止我尝试使用 DENSE_RANK() 实现此目的的代码。

declare @t1 table (ID char(3) not null,Name char(5) not null)
insert into @t1(ID,  Name) values
('ID1','Test1'),
('ID2','Test1'),
('ID3','Test2')

declare @t2 table (CusID char(3) not null,counter int not null)
insert into @t2(CusID,  counter) values
('A1', 100),
('A2', 200),
('A3', 300)


select ID,Name,'ExampleST' +
       RIGHT('00000' + CONVERT(varchar(4),
             DENSE_RANK() OVER (ORDER BY Name)+ counter)
       ,5) as NewID
from @t1
CROSS JOIN @t2
order by ID

这会返回:

ID  Name    NewID
ID1 Test1   ExampleST00101
ID1 Test1   ExampleST00201
ID1 Test1   ExampleST00301
ID2 Test2   ExampleST00102
ID2 Test2   ExampleST00202
ID2 Test2   ExampleST00302
ID3 Test3   ExampleST00103
ID3 Test3   ExampleST00203
ID3 Test3   ExampleST00303

我希望它返回什么

ID  Name    NewID
ID1 Test1   ExampleST00100
ID1 Test1   ExampleST00100
ID1 Test1   ExampleST00100
ID2 Test2   ExampleST00200
ID2 Test2   ExampleST00200
ID2 Test2   ExampleST00200
ID3 Test3   ExampleST00300
ID3 Test3   ExampleST00300
ID3 Test3   ExampleST00300

如何做到这一点?

【问题讨论】:

你能解释一下你想实现的逻辑吗?据我所知,您在@t2CROSS JOINing,其中包括100, 200, 300 的值。这意味着@t1 中的每一行都将与@t2 中的所有三行 匹配。但你说这不是你想要的? (您希望 ID1100 匹配,但不匹配 200300?) 您的窗口函数是否正确我无法判断,但您想要的输出肯定与您的 CROSS JOIN 相矛盾。 CROSS JOIN 用于有意创建笛卡尔积。 ID1 应链接到 A1、ID2、A2 等,但不能静态链接,因此可以将更多行插入到两个表中,并且无需更改脚本即可工作。 但是,您的笛卡尔积与您想要的输出相矛盾。根据CROSS JOIN 和 SQL 中的字符串操作,您应该为每个字符串获取三个不同字符串排在@t1; (ST001??ST002??ST003??)。但是,您希望每行的所有三个字符串都相同吗?为什么?请用英语对您希望实现的逻辑进行完整的功能解释。我现在只能说你的例子和你的 SQL 相互矛盾。 (注意;这些都与DENSE_RANK() 无关,这就是我寻求澄清的原因。) 另外,我注意到ID2 应该是TEST1,但您的示例输出状态为TEST2。不幸的是,差异太多,细节太少,无法确定您要达到的目标。 我可以看到您已经编辑了帖子。不幸的是,输出仍然与INSERT 语句不匹配INSERT 中的ID2 = TEST1,但在输出中它是TEST2,仍然不清楚关于为什么+ count 应该在所有三行中使用相同的@t1.id 给出相同的结果(而不是一行具有+100,另一行具有+200,最后一行具有+300等等等等。 【参考方案1】:

如果我理解正确,你不想要dense_rank(),你只想要每个名字的计数器的max()

select ID, Name,
       ('ExampleST' +
        right('00000' + cast(dense_rank() over (order by name) * 100 as varchar(255)),
              5) as NewID
from @t1 cross join
     @t2
order by ID;

【讨论】:

这只会为所有不正确的行返回 ST00300 @totalfreakingnoob 。 . .我明白你在说什么。我修复了逻辑,所以我认为它可以满足您的需求。

以上是关于使用 DENSE_RANK 拆分数据集的主要内容,如果未能解决你的问题,请参考以下文章

DENSE_RANK() 或 ROW_NUMBER() - 创建分组

Oracle 中 rownumrow_number()rank()dense_rank() 函数的用法

好用的排名函数~ROW_NUMBER(),RANK(),DENSE_RANK() 三兄弟

将 Oracle 查询中的 keep dense_rank 转换为 postgres

Oracle:row_number()rank()dense_rank()

DENSE_RANK 根据特定顺序