SQL父子和继承

问题描述 投票:0回答:2

我正在使用SQL Server 2016,我希望有人可以帮我解决这个问题。

我有一个表,它包含相同记录和它们的属性之间的关系。这是一个示例表。

CREATE TABLE [Family] ([Id] Int NOT NULL, [Relation] VARCHAR(12), [Level] TinyInt,  [Shoes] VARCHAR(12), [Shirt] VARCHAR(12), [Coat] VARCHAR(12))

INSERT INTO [Family] ([Id], [Relation], [Level], [Shoes], [Shirt], [Coat])
   VALUES (1, 'Grandparent', 1, 'Blue', 'Brown', 'Green'),
          (1, 'Parent',2, 'Red', NULL, NULL),
          (1, 'Child', 3, NULL, 'Yellow', NULL),
          (2, 'Grandparent', 1, 'Purple', 'Grey', 'Blue'),
          (2, 'Parent',2, NULL, 'Brown', 'Green')
          (2, 'Child', 3, NULL, NULL, 'Yellow');

关键字段是Id和a Level。规则是我希望能够为每个id选择并返回一行,其中属性返回具有最高级别非空的那一行。即如果值为null,则从下一个较低级别继承。

我希望我解释正确,所以结果看起来像这样:

Id          Shoes  Shirt  Coat
----------- ------ ------ ------
1           Red    Yellow Green
2           Purple Brown  Yellow

我已经尝试了几种与ISNULL和函数的方法,但它们最终变得混乱并且很慢。当然,我在这里发布的是一个简单的例子,真正的表将有8-10个级别和20多列属性,我需要它来执行大型数据集。

我周围有一次打猎,没有找到真正匹配的东西,谢谢

sql sql-server
2个回答
1
投票

我只是想试试这个。 显然,在像FIRST_VALUE这样的窗口函数之后处理DISTINCT。

SELECT DISTINCT Id, 
 FIRST_VALUE(Shoes) OVER (PARTITION BY Id ORDER BY IIF(Shoes is null,0,Level) DESC) AS Shoes,
 FIRST_VALUE(Shirt) OVER (PARTITION BY Id ORDER BY IIF(Shirt is null,0,Level) DESC) AS Shirt,
 FIRST_VALUE(Coat)  OVER (PARTITION BY Id ORDER BY IIF(Coat is null,0,Level) DESC) AS Coat
FROM Family;

结果:

Id  Shoes   Shirt   Coat

1   Red     Yellow  Green
2   Purple  Brown   Yellow

对rextester here的测试


0
投票

我想到的第一件事是下一个想法:

select f.Id,shoes.Shoes,shirt.Shirt,coat.Coat from [Family] f
left join (select top 1 with ties Id,Shoes from [Family] order by ROW_NUMBER() over (partition by Id order by case when Shoes is not null then [Level] else null end) desc) shoes
    on shoes.Id = f.Id
left join (select top 1 with ties Id,Shirt from [Family] order by ROW_NUMBER() over (partition by Id order by case when Shirt is not null then [Level] else null end) desc) shirt
    on shirt.Id = f.Id
left join (select top 1 with ties Id,Coat from [Family] order by ROW_NUMBER() over (partition by Id order by case when Coat is not null then [Level] else null end) desc) coat
    on coat.Id = f.Id
group by f.Id,shoes.Shoes,shirt.Shirt,coat.Coat
order by f.Id
© www.soinside.com 2019 - 2024. All rights reserved.