一次查询可根据不同条件从同一张表中将一列数据分成两列[SQL]

时间:2020-06-11 10:25:38

标签: sql sql-server string tsql pivot

我在表中有以下数据,这是从表中显示的具有多列的单列,但是仅需要使用查询将该列中的数据提取到两列输出中:

+----------------+--+
| DataText       |  |
| 1 DEC20 DDD    |  |
| 1 JUL20 DDD    |  |
| 1 JAN21 DDD    |  |
| 1 JUN20 DDD500 |  |
| 1 JUN20 DDD500 |  |
| 1 JUN20DDDD500 |  |
| 1 JUN20DDDD500 |  |
| 1 JUL20 DDD800 |  |
| 1 JUL20 DDD800 |  |
| 1 JUL20DDDD800 |  |
| 1 JUL20DDDD400 |  |
| 1 JUL20DDDD400 |  |
+----------------+--+

所需结果:基于数据的前13个字符的不同值,基于“长数据”和“短数据”分为两列,但两列的输出仅给出前13个字符:

+-------------+-------------+
| ShortData   | LongData    |
| 1 DEC20 DDD | 1 JUN20 DDD |
| 1 JUL20 DDD | 1 JUN20DDDD |
| 1 JAN21 DDD | 1 JUL20 DDD |
|             | 1 JUL20DDDD |
+-------------+-------------+

类似的东西:

Select
(Select DISTINCT LEFT(DataText,13)
From myTable)
Where LEN(DataText)=13) As ShortData
 ,
(Select DISTINCT LEFT(DataText,13)
From myTable)
Where LEN(DataText)>13) As LongData

如果可能的话,我也只想查询/“扫描”该表一次。我无法修改任何SO示例来使这种查询正常工作。

1 个答案:

答案 0 :(得分:2)

这很丑陋,但可行。首先,您需要一个定义行顺序的列-我假设您有这样的列,称为id

然后,您可以选择不同的文本,根据它们的长度将它们放在不同的组中,最后旋转:

select
    max(case when grp = 0 then dataText end) shortData,
    max(case when grp = 1 then dataText end) longData
from (
    select 
        dataText, 
        grp,
        row_number() over(partition by grp order by id) rn
    from (
        select
            id,
            case when len(dataText) <= 13 then 0 else 1 end grp,
            substring(dataText, 1, 13) dataText 
        from (select min(id) id, dataText from mytable group by dataText) t
    ) t
) t
group by rn

如果您对按字符串列本身对记录进行排序感到满意,那么它会更简单(对于示例数据,它会产生相同的结果):

select
    max(case when grp = 0 then dataText end) shortData,
    max(case when grp = 1 then dataText end) longData
from (
    select 
        dataText, 
        grp,
        row_number() over(partition by grp order by dataText) rn
    from (
        select distinct
            case when len(dataText) <= 13 then 0 else 1 end grp,
            substring(dataText, 1, 13) dataText 
        from mytable
    ) t
) t
group by rn

Demo on DB Fiddle

shortData   | longData     
:---------- | :------------
1 DEC20 DDD | 1 JUL20 DDD80
1 JAN21 DDD | 1 JUL20DDDD40
1 JUL20 DDD | 1 JUL20DDDD80
null        | 1 JUN20 DDD50
null        | 1 JUN20DDDD50