TSQL вычисляет значение строки на основе значений других строк - PullRequest
0 голосов
/ 22 октября 2019

У меня есть таблица с именем WORDS, например:

------------------------------
Symbol          ParentSymbol
------------------------------
a
ab
abc
abd
abda
abdb
b
ba
bb
bbbc
bbc
abcd
bbbbbbbbbbbbba

Я хочу обновить столбец ParentSymbol следующим образом:

------------------------------
Symbol          ParentSymbol
------------------------------
a
ab              a
abc             ab
abd             ab
abda            abd
abdb            abd
b
ba              b
bb              b
bbbc            bb
bbc             bb
abcd            abc
bbbbbbbbbbbbba  bb 
------------------------------

Столбец ParentSymbol содержит только значения из столбца символов. или ноль, если родитель не найден.

Я имею в виду какое-то соединение, основанное на разбиении по подстроке Symbol, но я не знаю как.

Есть ли способ добиться этого

Ответы [ 3 ]

3 голосов
/ 22 октября 2019

Символ ParentSymbol только на одну букву меньше?

UPDATE w
SET    ParentSymbol = left(Symbol, len(Symbol) - 1)
FROM   WORDS w

обновленный запрос

UPDATE  w
SET     ParentSymbol = ISNULL(p.ParentSymbol, '')
FROM    WORDS w
        OUTER APPLY
        (
            SELECT  TOP 1 ParentSymbol = x.Symbol
            FROM    WORDS  x
            WHERE   x.Symbol    <> w.Symbol
            AND     w.Symbol    LIKE x.Symbol + '%'
            ORDER BY x.Symbol DESC
         ) p
1 голос
/ 22 октября 2019

Следующий код сначала находит ближайший к значению подстроку.

/*
create table #words (Symbol varchar(100), ParentSymbol varchar(100));
insert into #words (Symbol) values ('a')
insert into #words (Symbol) values ('ab')
insert into #words (Symbol) values ('abc')
insert into #words (Symbol) values ('abd')
insert into #words (Symbol) values ('abda')
insert into #words (Symbol) values ('abdb')
insert into #words (Symbol) values ('b')
insert into #words (Symbol) values ('ba')
insert into #words (Symbol) values ('bb')
insert into #words (Symbol) values ('bbbc')
insert into #words (Symbol) values ('bbc')
insert into #words (Symbol) values ('abcd')
*/

with cte as(
select w2.Symbol  as ChildSymbol,
        max(w.Symbol) as Symbol
from #words as w
    inner join #words as w2 ON w.Symbol <> w2.Symbol and charindex(w.Symbol,w2.Symbol) = 1
group by w2.Symbol
)
select w.Symbol,
        c.Symbol as ParentSymbol
from #words as w
    left outer join cte as c ON w.Symbol = c.ChildSymbol
0 голосов
/ 22 октября 2019

Я пытаюсь использовать dense_rank и row_number оконные функции.

Вторая попытка -

declare @table table (Symbol varchar(10));
insert into @table values 
('a')
,('ab')
,('abc')
,('abd')
,('abda')
,('abdb')
,('b')
,('ba')
,('bb')
,('bbbc')
,('bbc')
,('abcd');

;with cte as (
    select left(symbol, 1) as FirstSymbol
    from @table
    group by left(symbol, 1)
),
cte2 as (
    select *, ROW_NUMBER() over (partition by b.firstSymbol order by a.symbol) as RankInGroup
    from @table as a
    left join cte as b on left(a.Symbol, 1) = b.FirstSymbol
)
select a.Symbol as Symbol, b.Symbol as ParentSymbol
from cte2 as a
left join cte2 as b on a.FirstSymbol = b.FirstSymbol and a.RankInGroup = b.RankInGroup + 1;

Первая попытка -

declare @table table (Symbol varchar(10));
insert into @table values 
('a')
,('ab')
,('abc')
,('abd')
,('abda')
,('abdb')
,('b')
,('ba')
,('bb')
,('bbbc')
,('bbc')
,('abcd');
--select * from @table;

;with cte as (
    select
        symbol,
        dense_rank() over (
            order by (
                case
                    when symbol like 'a%' then 1 when symbol like 'b%' then 2 when symbol like 'c%' then 3 when symbol like 'd%' then 4
                    when symbol like 'e%' then 5 when symbol like 'f%' then 6 when symbol like 'g%' then 7 when symbol like 'h%' then 8
                    when symbol like 'i%' then 9 when symbol like 'j%' then 10 when symbol like 'k%' then 11 when symbol like 'l%' then 12
                    when symbol like 'm%' then 13 when symbol like 'n%' then 14 when symbol like 'o%' then 15 when symbol like 'p%' then 16
                    when symbol like 'q%' then 17 when symbol like 'r%' then 18 when symbol like 's%' then 19 when symbol like 't%' then 20
                    when symbol like 'u%' then 21 when symbol like 'v%' then 22 when symbol like 'w%' then 23 when symbol like 'x%' then 24
                    when symbol like 'y%' then 25 when symbol like 'z%' then 26
            end)
        ) as GroupNumber,
        row_number() over (
            partition by (
                case
                    when symbol like 'a%' then 1 when symbol like 'b%' then 2 when symbol like 'c%' then 3 when symbol like 'd%' then 4
                    when symbol like 'e%' then 5 when symbol like 'f%' then 6 when symbol like 'g%' then 7 when symbol like 'h%' then 8
                    when symbol like 'i%' then 9 when symbol like 'j%' then 10 when symbol like 'k%' then 11 when symbol like 'l%' then 12
                    when symbol like 'm%' then 13 when symbol like 'n%' then 14 when symbol like 'o%' then 15 when symbol like 'p%' then 16
                    when symbol like 'q%' then 17 when symbol like 'r%' then 18 when symbol like 's%' then 19 when symbol like 't%' then 20
                    when symbol like 'u%' then 21 when symbol like 'v%' then 22 when symbol like 'w%' then 23 when symbol like 'x%' then 24
                    when symbol like 'y%' then 25 when symbol like 'z%' then 26
            end) order by symbol
        ) as RankInGroup
    from @table
)
select a.Symbol as Symbol, b.Symbol as ParentSymbol
from cte a
left join cte b on a.GroupNumber = b.GroupNumber and a.RankInGroup = b.RankInGroup + 1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...