SQL单独|将值分成新列-从右到左排序

时间:2018-07-10 19:12:42

标签: sql sql-server

我有一个层次结构,已经能够采用以下格式(从中获取的电子表格是一团糟):

enter image description here

我需要从AllLevels列中获取值并创建一个具有以下列名称的新表:

RegionLevel1 RegionLevel2 RegionLevel3 RegionLevel4 CountryCode FullPath HierarchyName

这就是窍门-第一个'|'之前的所有内容始终为Level1,最后一个'|'之后的值始终是Level4。但是看看“中央” | “波兰” | PL。应该这样

1级-中央,2级-波兰,3级-NULL,4级-PL

我以为我对此有些了解,但事实并非如此。有人可以帮忙吗?

这是我用来从原始表创建此CTE的位置:

    with  child as
        ( 
        select  ParentCode
             ,      countrycode    
             , Cast (countrycode as varchar(100)) as Level
        from    [dbo].[rawCountryHierarchy]
        where   CountryCode IN (SELECT DISTINCT TRIM(LEFT(BillingLocation, CHARINDEX('-', BillingLocation)-1)) FROM FactSales)
        union all 
        select  e.parentcode
             ,            e.countrycode
             ,            cast (cast(e.countrycode as varchar(100))+' | '+level as varchar(100)) as level
        from    child m
        join    [dbo].[rawCountryHierarchy] e
        on      m.parentcode= e.countrycode
        )

--insert into [dbo].[DimCountryHierarchy]
select  c.ParentCode, c.CountryCode AS rawCountryCode, cast (cast(c.ParentCode as varchar(100))+' | '+level as varchar(100)) as AllLevels, CASE WHEN Level like '%|%' THEN trim(right(level, charindex('|', reverse(level))-1)) END AS CountryCode, r.HierarchyName
from    child c  
inner join rawRegion on c.parentcode = rawRegion.RegionCode
left join rawCountryHierarchy r on  CASE WHEN Level like '%|%' THEN trim(right(level, charindex('|', reverse(level))-1)) END = r.CountryCode
order by AllLevels
option  (maxrecursion 0)

在这里,我从以下国家/地区获取国家/地区代码:

WHERE CountryCode IN (SELECT DISTINCT TRIM(LEFT(BillingLocation, CHARINDEX('-', BillingLocation)-1)) FROM FactSales)

所以实际上代表了最低水平。

编辑: 我尝试填充的新表中的列如下:

RegionLevel1 RegionLevel2 RegionLevel3 RegionLevel4 CountryCode FullPath HierarchyName

RegionLevel1始终是图片AllLevels列中的第一个值。 CountryCode始终是最后一个“ |”之后的最后一个值在所有级别列中。在AllLevels列的First和Last值之间,RegionLevel2,RegionLevel3和RegionLevel4列将从左到右填充(即,在第一行的情况下,它看起来像:RegionLevel1-Africa,RegionLevel2-Export,RegionLevel3-WestAfrica ,RegionLevel4-NULL,CountryCode-NG),然后用AllLevels列填充FullPath,而HierarchyName则填充新表中的同一列。

2 个答案:

答案 0 :(得分:0)

您要解决的问题对我来说似乎无法解决。有时数据太脏了,在这里可能就是这种情况。您如何知道Level1-中央,Level2-波兰,Level3-NULL,Level4-PL和Level1-中央,Level2-波兰,Level3-PL之间的区别 问题在于,数据没有使用级别3和4的正确分隔符输入。 如果以Central | Poland || PL(针对第4级)或Central | Poland | PL(针对第3级)的形式出现,则可以解决,但是使用您提供的这些数据,无法准确知道3和4级我可以看到

答案 1 :(得分:0)

此方法使用DelimitedSplit8K拆分值,然后旋转它们。可能有点矫kill过正,但这是一个不同的选择,可能值得尝试:

USE Sandbox;
GO

CREATE TABLE dbo.AllLevels (ID int IDENTITY(1,1), --I ASSUME you have an ID column
                            Levels varchar(8000));
INSERT INTO dbo.AllLevels (Levels)
VALUES ('Africa | Export | West Africa | NG'),
       ('Austria | ATALL | AT'),
       ('Central | HU');

GO

WITH Split AS(
    SELECT AL.ID, AL.Levels,
           LTRIM(RTRIM(DS.Item)) AS [Level],
           DS.ItemNumber AS LevelNumber,
           MAX(DS.ItemNumber) OVER (PARTITION BY ID) AS MaxLevel
    FROM dbo.AllLevels AL
         CROSS APPLY dbo.DelimitedSplit8K(AL.Levels,'|') DS),
Pivots AS(
    SELECT ID,
           MAX(CASE WHEN LevelNumber = 1 AND LevelNumber < MaxLevel THEN [Level] END) AS Level1,
           MAX(CASE WHEN LevelNumber = 2 AND LevelNumber < MaxLevel THEN [Level] END) AS Level2,
           MAX(CASE WHEN LevelNumber = 3 AND LevelNumber < MaxLevel THEN [Level] END) AS Level3,
           MAX(CASE WHEN LevelNumber = 4 OR LevelNumber = MaxLevel THEN [Level] END) AS Level4
    FROM Split
    GROUP BY ID)
SELECT *
FROM Pivots P
     JOIN dbo.AllLevels AL ON P.ID = AL.ID;

GO
DROP TABLE dbo.AllLevels;