使用SQL条件提取固定宽度的数据

时间:2018-10-17 14:36:16

标签: sql sql-server fixed-width

我有一个场景,我从多个表中提取数据,并且输出为固定宽度格式。固定宽度的输出如下所示:

当前输出:

1001RJOHNKEITH25 20181017 NA
1002CDWANEKANE36 20181010 RR
1003CMIKAYLAGN44 20181011 RR

所需的输出:

1001RJOHNKEITH25 20181017 NA
1002CDWANEKANE36          NA
1003RMIKAYLAGN44 20181010 RR

在此输出中,1001是人员ID,R / C是硬编码的指示器,然后是名称,年龄和注册日期,记录类型。注册日期有一个条件。如果记录指示符是R,则将显示注册日期。否则,它应该为null。我不确定如何根据固定宽度字段编写条件。

附件中的妊娠期演示:https://rextester.com/MKESI50760

有帮助吗?!

5 个答案:

答案 0 :(得分:1)

您只需要更新查询中的一行:

LEFT(CONCAT(isnull(t.registrationdate,''),space(14)),14), -- Registration date should show up when record indicator is 'R'

成为

LEFT(CONCAT(isnull(CASE WHEN t.registeredonline = '1' and t.recordtype = 'NA' THEN CONVERT(char(10), t.registrationdate,126) ELSE NULL END,''),space(14)),14), -- Registration date should show up when record indicator is 'R'

当记录指示符的逻辑评估为“ R”时,这将检查您的日期字段并放入空格而不是日期

需要'convert'语句,否则NULL日期将最终显示为1900-01-01。

希望有帮助。

答案 1 :(得分:1)

LEFT(CONCAT(isnull(t.registrationdate,''),space(14)),14)

成为

CASE WHEN t.registeredonline = '1' and t.recordtype = 'NA' THEN LEFT(CONCAT(isnull(t.registrationdate,''),space(14)),14) ELSE SPACE(14) END, --     Registration date should show up when record indicator is 'R'

只需用条件将原始行括起来,看看结果是否为'R'。 该条件显示在您的链接的查询中。

答案 2 :(得分:1)

好的,这有点混乱。但是由于输出是固定宽度的,因此您始终可以将查询放入视图或CTE中(如下所示),然后通过SUBSTRING函数访问字符串中的特定位置。

这样做有很多缺点。如果有人更改了要连接的字段的顺序或大小,则一切都会中断。因此,本着回答您的问题的精神..这是一种解决方法。但是我认为这不是一个好方法。

WITH BaseQuery as

(
    select 
    t.Cid,
    cast
    (
     concat(
         LEFT(CONCAT(isnull(t.Cid,''),space(5)),5), -- PersonID
         LEFT(CONCAT(isnull
              ((case when t.registeredonline = '1' and t.recordtype = 'NA' then 'R'
                    else 'C' end),''),space(10)),10),-- Record Indicator
         LEFT(CONCAT(isnull(t.name,''),space(14)),14), --name
         LEFT(CONCAT(isnull(t.age,''),space(5)),5), --age
         LEFT(CONCAT(isnull(t.registrationdate,''),space(14)),14), -- Registration date should show up when record indicator is 'R'
         LEFT(CONCAT(isnull(t.recordtype,''),space(3)),3) --Record type  
         ) as nvarchar(max) 
        ) result
     from #temp t
)

SELECT
    CONCAT(
        SUBSTRING(result, 1, 34) -- portion before the 'registration date' region
        , CASE WHEN SUBSTRING (RESULT, 6, 1) = 'R' THEN SUBSTRING (RESULT, 35, 10) ELSE SPACE(10) END 
        , SUBSTRING (RESULT, 46, 5)
        )

FROM 
    BaseQuery

这给出结果:

1001 R         JOHNKEITH     25   2018-10-17   NA
1002 C         DWANEKANE     36                RR
1003 C         JOHNKEITH     44                RR

答案 3 :(得分:1)

使用固定宽度的数据进行处理:

  

固定宽度的文本文件或字符串中的数据按行排列,   列,每行一个条目。每列都有固定的宽度,   以字符指定,它确定最大数据量   它可以包含。没有定界符用于分隔字段中的字段   文件。

在T-SQL中解析该数据,您可以使用SUBSTRING

https://docs.microsoft.com/en-us/sql/t-sql/functions/substring-transact-sql?view=sql-server-2017

SUBSTRING ( expression ,start , length ) 

这是一个例子:

DECLARE @SampleData TABLE
    (
        [LineData] NVARCHAR(255)
    );

INSERT INTO @SampleData (
                            [LineData]
                        )
VALUES ( '1001RJOHNKEITH25 20181017 NA' )
     , ( '1002CDWANEKANE36 20181010 RR' )
     , ( '1003CMIKAYLAGN44 20181011 RR' );

SELECT SUBSTRING([LineData], 1, 4) AS [PersonId]
     , SUBSTRING([LineData], 5, 1) AS [Indicator]
     , SUBSTRING([LineData], 6, 9) AS [Name]
     , SUBSTRING([LineData], 15, 2) AS [Age]
     , SUBSTRING([LineData], 18, 8) AS [RegDate]
     , SUBSTRING([LineData], 27, 2) AS [RecordType]
     , *
FROM   @SampleData;

因此,在您的示例中,您需要评估“指标”是否为“ R”,您可以使用以下方法获得该值:

SUBSTRING([LineData], 5, 1)

不确定如何适应您的任务。根据其他评论,还有更多有关如何确定“指标”的信息。

不太理想,但是您可以解析所有字段,然后将它们放回去进行该指标字段的评估,或者在评估指标是否为R时使用case语句中的内容将日期替换为空白。

DECLARE @SampleData TABLE
    (
        [LineData] NVARCHAR(255)
    );

INSERT INTO @SampleData (
                            [LineData]
                        )
VALUES ( '1001RJOHNKEITH25 20181017 NA' )
     , ( '1002CDWANEKANE36 20181010 RR' )
     , ( '1003CMIKAYLAGN44 20181011 RR' );

--We check for R using substring
--when not equal to R we replace where Registration date in the string was with blanks.
SELECT CASE WHEN SUBSTRING([LineData], 5, 1) = 'R' THEN [LineData]
            ELSE STUFF([LineData], 18, 8, '        ')
       END AS [LineData]
FROM   @SampleData;

答案 4 :(得分:-1)

选择ColA,然后选择ColB(在此处为标准),然后以NULL ELSE ColB结尾,以ColB,ColC结尾