我有桌子
ID MIN_ID
1 1
2 1
3 1
4 4
5 1
6 5
7 6
8 4
我需要第三列FINAL_ID,如果ID = MIN_ID则返回MIN_ID,否则它将在表中递归查找,直到找到ID = MIN_ID的行。结果应该是
ID MIN_ID FINAL_ID
1 1 1
2 1 1
3 1 1
4 4 4
5 1 1
6 5 1 // 5 have the MIN_ID of 1
7 6 1 // 6 have the MIN_ID of 1 and 5 have the MIN_ID of 1.
8 4 4 // 8 goes to 4, 4 goes to 4. Done.
问题是如何在SQL中没有任何过程语言的情况下获得此结果。任何DBMS示例都适合(MySQL,PostgreSQL,DB2,SQL Server,Oracle)
例如执行它的php代码:
<?php
$table = [
['ID' => '1', 'MIN_ID' => '1'],
['ID' => '2', 'MIN_ID' => '1'],
['ID' => '3', 'MIN_ID' => '1'],
['ID' => '4', 'MIN_ID' => '4'],
['ID' => '5', 'MIN_ID' => '1'],
['ID' => '6', 'MIN_ID' => '5'],
['ID' => '7', 'MIN_ID' => '6'],
];
for ($x = 0; $x < count($table); $x++) {
$table[$x]['FINAL_ID'] = calculate_final_id($table, $table[$x]);
}
print_r($table);
function calculate_final_id($table, $row)
{
if ($row['ID'] == $row['MIN_ID']) {
return $row['ID'];
}
$next_row = search($table, $row['MIN_ID']);
return calculate_final_id($table, $next_row);
}
function search($table, $id)
{
for ($x = 0; $x < count($table); $x++) {
if ($table[$x]['ID'] == $id) {
return $table[$x];
}
}
}
答案 0 :(得分:2)
SQL Server示例。建立在ID的订单
CREATE TABLE myTable
(ID int, MIN_ID int);
INSERT INTO myTable
(ID, MIN_ID)
VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 4),
(5, 1),
(6, 5),
(7, 6)
;
WITH rc AS (
SELECT ID, MIN_ID as FinalId
FROM myTable
UNION ALL
SELECT rc.ID, t.MIN_ID
FROM rc
JOIN myTable t ON rc.FinalId = t.ID AND t.ID != t.MIN_ID
)
SELECT ID, min(FinalId) FinalId
FROM rc
GROUP BY ID;
答案 1 :(得分:1)
这应该有效(表变量的SQL Server语法):
declare @t table (ID int not null, MIN_ID int not null)
insert into @t(ID,MIN_ID) values
(1,1),
(2,1),
(3,1),
(4,4),
(5,1),
(6,5),
(7,6)
;With Search as (
select
ID,MIN_ID,MIN_ID as FINAL_ID,0 as Depth
from @t
union all
select
s.ID,s.MIN_ID,t.MIN_ID,Depth+1
from
Search s
inner join
@t t
on
s.FINAL_ID = t.ID
where
s.FINAL_ID != t.MIN_ID
), Ordered as (
select *,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Depth desc) as rn
from Search
)
select *
from Ordered
where rn = 1
基本上,如果可以,我们会继续重新计算FINAL_ID
并跟踪我们搜索的深度 - 然后为每个ID
值选择最深的结果。
结果:
ID MIN_ID FINAL_ID Depth rn
----------- ----------- ----------- ----------- --------------------
1 1 1 0 1
2 1 1 0 1
3 1 1 0 1
4 4 4 0 1
5 1 1 0 1
6 5 1 1 1
7 6 1 2 1
(递归CTE(Search
)和窗口函数(ROW_NUMBER
)是应该在任何现代SQL数据库上工作的标准SQL)
答案 2 :(得分:0)
根据我的意见,我认为您想使用CASE
声明。
SELECT ID, MIN_ID, CASE WHEN ID = MIN_ID THEN MIN_ID ELSE 1 END AS FINAL_ID
FROM yourtable
输出:
ID MIN_ID FINAL_ID
1 1 1
2 1 1
3 1 1
4 4 4
5 1 1
6 5 1
7 6 1