Разделить строку и отобразить ниже других данных столбца с помощью SQL Server [duplicate]

Я попытался с помощью combByKey, вот мои шаги

combineddatardd=sc.parallelize([("A", 3), ("A", 9), ("A", 12),("B", 4), ("B", 10), ("B", 11)])

combineddatardd.combineByKey(lambda v:[v],lambda x,y:x+[y],lambda x,y:x+y).collect()

Выход:

[('A', [3, 9, 12]), ('B', [4, 10, 11])]
  1. Определить функцию для объединителя, которая устанавливает аккумулятор в первую пару значений ключа который он встречает внутри раздела, преобразует значение, указанное на этом шаге
  2. Определяет функцию, которая слияния нового значения того же ключа с значением аккумулятора, захваченным на шаге 1. Примечание: -конвертировать значение для списка в эта функция как значение аккумулятора была преобразована в список на первом этапе
  3. Определить функцию для объединения выходов комбинированных отдельных разделов.
1
задан Rich Seller 21 July 2009 в 20:19
поделиться

6 ответов

Взгляните на эту функцию. Я сделал аналогичные трюки для разделения и переноса данных в Oracle. Переверните данные, вставляя декодированные значения в временную таблицу. Конфликт в том, что MS позволит вам сделать это «на лету», в то время как Oracle требует явной таблицы temp.

Функция разделения MS SQL Функция лучшего разделения

Редактировать автор: Это сработало отлично. Окончательный код выглядел так (после создания функции split):

select pv.productid, colortable.items as color
from product p 
    cross apply split(p.color, ',') as colortable
9
ответ дан TheSoftwareJedi 28 August 2018 в 19:20
поделиться
  • 1
    эти петли будут медленными, я бы поставил деньги, чтобы мой запрос курил его в любой день ... – KM. 31 March 2009 в 22:31
  • 2
    Для SQL 2016 вы можете использовать встроенную функцию: CROSS APPLY STRING_SPLIT(p.color, ',') – Dave 18 October 2016 в 20:23

Я бы создал для этой функции CLR-таблицу:

http://msdn.microsoft.com/en-us/library/ms254508 (VS.80) .aspx

Причиной этого является то, что код CLR будет намного лучше разбирать строки (вычислительную работу) и может передать эту информацию в виде набора, что действительно является SQL Server

Функция CLR вернет серию записей на основе проанализированных значений (и значения входного идентификатора).

Затем вы использовали бы КРЕСТНОЕ ПРИМЕНЕНИЕ на каждый элемент вашей таблицы.

0
ответ дан casperOne 28 August 2018 в 19:20
поделиться
  • 1
    ИМХО, это слишком много для чего-то такого тривиального. – James 31 March 2009 в 21:54
  • 2
    @James: Это действительно просто, намного проще, чем код, который вам нужно перепрыгнуть, чтобы анализировать стимулы в T-SQL, и это всегда будет быстрее при разборе. Крест применяется естественный выбор здесь, когда у вас есть ЛЮБАЯ функция, которая разбирает линии друг от друга. – casperOne 1 April 2009 в 06:11
  • 3
    в зависимости от количества или строк для обработки и длины цветов CSV, CLR не будет масштабироваться. В этом примере это будет работать в 3-х строках, но если вы каждый раз запускаете этот запрос каждый день, он будет медленным. Чистый SQL-запрос, такой как мой, будет намного быстрее. – KM. 1 April 2009 в 12:49
  • 4
    @mike: Это абсолютно неправда, и я призываю вас показать тесты, чтобы доказать это. CLR масштабируется просто отлично, учитывая, что SQL Server управляет всем, что требуется CLR (память, потоки), поэтому он не может стать слишком жадным. Кроме того, CLR всегда будет лучше на процедурный код, подобный этому. – casperOne 1 April 2009 в 18:04
  • 5
    @mike: Я бы хотел показать вам свои собственные тесты кода CLR и T-SQL при разборе строк. Я видел где-то с 30% -200% -ным увеличением скорости при обработке строк менее 10000 символов, причем все методы превышают 100000 символов или около того. – casperOne 1 April 2009 в 18:18

Вы можете попробовать это, не требуя каких-либо дополнительных функций:

declare @t table (col1 varchar(10), col2 varchar(200))
insert @t
          select '1', 'red,blue,green'
union all select '2', NULL
union all select '3', 'green,purple'


select col1, left(d, charindex(',', d + ',')-1) as e from (
    select *, substring(col2, number, 200) as d from @t col1 left join
        (select distinct number from master.dbo.spt_values where number between 1 and 200) col2
        on substring(',' + col2, number, 1) = ',') t
4
ответ дан Christopher Klein 28 August 2018 в 19:20
поделиться
  • 1
    GREAT ANSWER, это гораздо лучший вопрос, чем моя первая попытка. См. Мой ответ для модифицированной версии этого. Использование значений псевдонимов таблиц, которые совпадают с именами столбцов, сбивает с толку, а использование системной таблицы для чисел заставляет вас использовать дополнительную производную таблицу. Помимо этого, БОЛЬШАЯ РАБОТА! – KM. 1 April 2009 в 13:21

Исправить вашу базу данных, если это вообще возможно. Списки с разделителями-запятыми в ячейках базы данных указывают на ошибочную схему в 99% случаев или более.

0
ответ дан Joel Coehoorn 28 August 2018 в 19:20
поделиться
  • 1
    Я согласен, но это действительно не помогает. – TheSoftwareJedi 31 March 2009 в 22:08
  • 2
    запрошенный набор результатов - лучший дизайн, просто введите «INTO YourNewTableName» и «INTO YourNewTableName». между списком выбора и FROM запроса, и будет создана новая таблица, где цвета будут разделены. – KM. 1 April 2009 в 12:39
  • 3
    Как вы предлагаете плакат исправить свою базу данных без ответа на этот вопрос? -1 – brian 16 April 2009 в 17:13
  • 4
    Во время поста не было ясно, что он фиксирует db, а не строит на нем. – Joel Coehoorn 16 April 2009 в 17:19

на основе ваших таблиц:

create table test_table
(
     ProductId  int
    ,Color      varchar(100)
)

insert into test_table values (1, 'red, blue, green')
insert into test_table values (2, null)
insert into test_table values (3, 'purple, green')

создать новую таблицу следующим образом:

CREATE TABLE Numbers
(
    Number  int   not null primary key
)

, которая имеет строки, содержащие значения от 1 до 8000 или около того.

это вернет вам то, что вы хотите:

EDIT вот намного лучший запрос, слегка измененный из большого ответа от @Christopher Klein:

Я добавил «LTRIM () «поэтому пробелы в списке цветов будут обработаны правильно:« красный, синий, зеленый ». Его решение не требует пробелов «красный, синий, зеленый». Кроме того, я предпочитаю использовать свою собственную таблицу Number и не использовать master.dbo.spt_values, это также позволяет удалить одну производную таблицу.

SELECT
    ProductId, LEFT(PartialColor, CHARINDEX(',', PartialColor + ',')-1) as SplitColor
    FROM (SELECT 
              t.ProductId, LTRIM(SUBSTRING(t.Color, n.Number, 200)) AS PartialColor
              FROM test_table             t
                  LEFT OUTER JOIN Numbers n ON n.Number<=LEN(t.Color) AND SUBSTRING(',' + t.Color, n.Number, 1) = ','
         ) t

EDIT END

SELECT
    ProductId, Color --,number
    FROM (SELECT
              ProductId
                  ,CASE
                       WHEN LEN(List2)>0 THEN LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(',', List2, number+1)-number - 1)))
                       ELSE NULL
                   END AS Color
                  ,Number
              FROM (
                       SELECT ProductId,',' + Color + ',' AS List2
                           FROM test_table
                   ) AS dt
                  LEFT OUTER JOIN Numbers n ON (n.Number < LEN(dt.List2)) OR (n.Number=1 AND dt.List2 IS NULL)
              WHERE SUBSTRING(List2, number, 1) = ',' OR List2 IS NULL
         ) dt2
    ORDER BY ProductId, Number, Color

вот мой результирующий набор:

ProductId   Color
----------- --------------
1           red
1           blue
1           green
2           NULL
3           purple
3           green

(6 row(s) affected)

, который тот же самый порядок вы хотите ...

5
ответ дан KM. 28 August 2018 в 19:20
поделиться
  • 1
    Это сделало именно то, что мне нужно. В моей ситуации я имел дело с данными, которые были объединены (несколько заказов на выполнение, которые выполнялись под одной и той же оплачиваемой позицией, мне нужно было разбить их, сохраняя номер позиции). – mounty 30 September 2011 в 19:50

Просто конвертируйте свои столбцы в xml и запросите его. Вот пример.

select 
    a.value('.', 'varchar(42)') c
from (select cast('<r><a>' + replace(@CSV, ',', '</a><a>') + '</a></r>' as xml) x) t1
cross apply x.nodes('//r/a') t2(a)
0
ответ дан nurettin 28 August 2018 в 19:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: