Разбейте данные в столбце базы данных записи на несколько записей - PullRequest
0 голосов
/ 09 сентября 2018

Azure SQL Server - у нас есть такая таблица:

MyTable

ID    Source     ArticleText
--    ------     -----------
1     100        <nvarchar(max) field with unstructured text from media articles>
2     145        "
3     866        "
4     232        "

ID столбец является первичным ключом и автоинкрементами на INSERTS.

Я выполняю этот запрос, чтобы найти записи с наибольшим размером данных в столбце ArticleText:

SELECT TOP 500 
    ID, Source, DATALENGTH(ArticleText)/1048576 AS Size_in_MB
FROM 
    MyTable
ORDER BY 
    DATALENGTH(ArticleText) DESC

Мы обнаруживаем, что по многим причинам как техническим, так и практическим данные в столбце ArticleText слишком велики в некоторых записях. Приведенный выше запрос позволяет мне взглянуть на диапазон размеров для наших самых больших записей, которые мне нужно знать для того, что я пытаюсь сформулировать здесь.

Подвиг, который мне нужно совершить, заключается в том, что для всех существующих записей в этой таблице любая запись, у которой ArticleText DATALENGTH больше X, разбивает эту запись на X записей, где каждая запись будет содержать одинаковое значение. в столбце Source, но разбейте данные в столбце ArticleText на эти записи на более мелкие фрагменты.

Как достичь этого, если говорить точное требование, взять все записи, у которых ArticleText DATALENGTH больше 10 МБ, и разбить каждую на 3 записи, в которых значение столбца Source результирующих записей одинаково для всех 3 записи, но данные ArticleText разделены на три части.

По сути, нам нужно разделить DATALENGTH на 3 и применить первые 1/3 текстовых данных к первой записи, 2-ю 1/3 ко 2-й записи и 3-ю 1/3 к третья запись.

Возможно ли это даже в SQL Server?

1 Ответ

0 голосов
/ 09 сентября 2018

Вы можете использовать следующий код для создания боковой таблицы с необходимыми данными:

CREATE TABLE #mockup (ID INT IDENTITY, [Source] INT, ArticleText NVARCHAR(MAX));

INSERT INTO #mockup([Source],ArticleText) VALUES
 (100,'This is a very long text with many many words and it is still longer and longer and longer, and even longer and longer and longer')
,(200,'A short text')
,(300,'A medium text, just long enough to need a second part');

DECLARE @partSize INT=50;

WITH recCTE AS
(
    SELECT ID,[Source]
          ,1 AS FragmentIndex
          ,A.Pos
          ,CASE WHEN A.Pos>0 THEN LEFT(ArticleText,A.Pos) ELSE ArticleText END AS Fragment
          ,CASE WHEN A.Pos>0 THEN SUBSTRING(ArticleText,A.Pos+2,DATALENGTH(ArticleText)/2) END AS RestString
    FROM #mockup
    CROSS APPLY(SELECT CASE WHEN DATALENGTH(ArticleText)/2 > @partSize 
                            THEN @partSize - CHARINDEX(' ',REVERSE(LEFT(ArticleText,@partSize)))
                            ELSE -1 END AS Pos) A

    UNION ALL
    SELECT r.ID,r.[Source]
         ,r.FragmentIndex+1
         ,A.Pos
         ,CASE WHEN A.Pos>0 THEN LEFT(r.RestString,A.Pos) ELSE r.RestString END
         ,CASE WHEN A.Pos>0 THEN SUBSTRING(r.RestString,A.Pos+2,DATALENGTH(r.RestString)/2) END AS RestString
    FROM recCTE r
    CROSS APPLY(SELECT CASE WHEN DATALENGTH(r.RestString)/2 > @partSize 
                            THEN @partSize - CHARINDEX(' ',REVERSE(LEFT(r.RestString,@partSize)))
                            ELSE -1 END AS Pos) A
    WHERE DATALENGTH(r.RestString)>0
)
SELECT ID,[Source],FragmentIndex,Fragment 
FROM recCTE
ORDER BY [Source],FragmentIndex;

GO
DROP TABLE #mockup

Результат

+----+--------+---------------+---------------------------------------------------+
| ID | Source | FragmentIndex | Fragment                                          |
+----+--------+---------------+---------------------------------------------------+
| 1  | 100    | 1             | This is a very long text with many many words and |
+----+--------+---------------+---------------------------------------------------+
| 1  | 100    | 2             | it is still longer and longer and longer, and     |
+----+--------+---------------+---------------------------------------------------+
| 1  | 100    | 3             | even longer and longer and longer                 |
+----+--------+---------------+---------------------------------------------------+
| 2  | 200    | 1             | A short text                                      |
+----+--------+---------------+---------------------------------------------------+
| 3  | 300    | 1             | A medium text, just long enough to need a second  |
+----+--------+---------------+---------------------------------------------------+
| 3  | 300    | 2             | part                                              |
+----+--------+---------------+---------------------------------------------------+

Теперь вам нужно обновить существующую строку значением FragmentIndex=1, в то время как вы должны вставить значения FragmentIndex>1. Сделайте это отсортированным по FragmentIndex, и ваш IDENTITY ID-столбец будет отображать правильный порядок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...