简体   繁体   English

将长字符串的查询结果拆分为T-SQL中的多行

[英]Split query results with long strings into multiple rows in T-SQL

I have a table in MS SQL Server that contains multiple TEXT fields that can have very long strings (from 0 characters to 100,000+ characters). 我在MS SQL Server中有一个表,其中包含多个TEXT字段,这些字段可以具有很长的字符串(从0个字符到100,000+个字符)。

I'd like to create a view (or a stored proc that populates a reporting table) that prepares this data for export to Excel, which has a certain character limit allowable per cell (32,767 chars). 我想创建一个视图(或填充报告表的存储过程),以准备将此数据导出到Excel,每个单元格具有一定的字符数限制(32,767个字符)。

It's relatively trivial to write a query to truncate the fields after a certain number of characters, but I'd like to create new rows containing the text that would be truncated. 编写查询以在一定数量的字符后截断字段是相对琐碎的,但是我想创建包含将被截断的文本的新行。

Example - Row 1, Col1 and Col3 contains text that is wrapped into 2 rows. 示例-第1行,Col1和Col3包含包装为2行的文本。

ID   |   COL1   |   COL 2   |   COL 3   |
1       AAAAAA     BBBBBBB     CCCCCC
1       AAA                    CC
2       XX         YY          ZZ   

You can try something along this: 您可以尝试以下方法:

A mockup table to simulate your issue 一个模拟表来模拟您的问题

DECLARE @tbl TABLE(ID INT IDENTITY, LongString VARCHAR(1000));
INSERT INTO @tbl VALUES('blah')
                      ,('blah blah')  
                      ,('blah bleh blih bloh')
                      ,('blah bleh blih bloh bluuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh');

--We can specify the chunk's length -我们可以指定块的长度

DECLARE @Chunk INT=6;

SELECT t.ID
      ,A.Nmbr AS ChunkNmbr
      ,SUBSTRING(t.LongString,A.Nmbr*@Chunk+1,@Chunk) AS ChunkOfString
FROM @tbl t
CROSS APPLY(SELECT TOP(LEN(t.LongString)/@Chunk + 1) 
                   ROW_NUMBER() OVER(ORDER BY (SELECT NULL))-1 
            FROM master..spt_values) A(Nmbr);

The idea in short: 简而言之:

We use a trick with APPLY and a computed TOP -clause. 我们对APPLY和计算好的TOP子句使用技巧。 The source master..spt_values is just a common table with a lot of rows. master..spt_values只是具有很多行的公用表。 We don't need the values, just a set to compute a running number using ROW_NUMBER() . 我们不需要这些值,只需要一个集合即可使用ROW_NUMBER()计算运行数字。 APPLY will be called row-by-row . APPLY将被称为逐行 That means, that a long string will create more numbers than a short one. 这意味着长字符串会比短字符串产生更多的数字。

To get your chunks I use a simple SUBSTRING() , where we compute the start of each chunk by rather simple multiplication. 为了获得块,我使用了一个简单的SUBSTRING() ,在这里我们通过相当简单的乘法来计算每个块的开始。

UPDATE: More than one column in one go 更新:一站式浏览多栏

Try this to use this approach for more than one column 尝试将此方法用于多于一列

DECLARE @tbl TABLE(ID INT IDENTITY, LongString1 VARCHAR(1000), LongString2 VARCHAR(1000));
INSERT INTO @tbl VALUES('blah','dsfafadafdsafdsafdsafsadfdsafdsafdsf')
                      ,('blah blah','afdsafdsafd')  
                      ,('blah bleh blih bloh','adfdsafdsafdfdsafdsafdafdsaasdfdsafdsafdsafdsafdsafsadfsadfdsafdsafdsafdsafdafdsafdsafadf')
                      ,('blah bleh blih bloh bluuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh','asdfdsaf');

DECLARE @Chunk INT=6;

SELECT t.ID
      ,A.MaxLen
      ,B.Nmbr AS ChunkNmbr
      ,SUBSTRING(t.LongString1,B.Nmbr*@Chunk+1,@Chunk) AS ChunkOfString1
      ,SUBSTRING(t.LongString2,B.Nmbr*@Chunk+1,@Chunk) AS ChunkOfString1
FROM @tbl t
CROSS APPLY(SELECT MAX(strLen) FROM (VALUES(LEN(t.LongString1)),(LEN(t.LongString2))) vals(strLen)) A(MaxLen)
CROSS APPLY(SELECT TOP(A.MaxLen/@Chunk + 1) 
                   ROW_NUMBER() OVER(ORDER BY (SELECT NULL))-1 
            FROM master..spt_values) B(Nmbr);

The new idea: We use an APPLY first to find the longest string in one row. 新思路:我们首先使用APPLY查找一行中最长的字符串。 We have to do the chunk computations only for this maximum number. 我们只需要为此最大数量进行块计算。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM