организация * сотрудники Фирма 1 * Иван Петров Ольга Иванова
Фирма 2 * Петр Петров
Фирма 3 * Олег Иванов Петр Петров Анна Петрова
тип значения "сотрудники" строка, разделитель - пробел
надо трансформировать к такому виду:
организация * сотрудники Фирма 1 * Иван Петров
Фирма 1 * Ольга Иванова
Фирма 2 * Петр Петров
Фирма 3 * Олег Иванов
Фирма 3 * Петр Петров
Фирма 3 * Анна Петрова
(1) в общем случае - никак. разделитель имен и "сотрудников" один и тот же.
Просто представьте, что появился сотрудник: Гассан Абдуррахман ибн Хоттаб. Это не два сотрудника, а один :)
Нужно структуру хранения переделывать.
(1) В вашем случае по нормальному НИКАК.
"Иван Петров Ольга Иванова" - может быть Иван это и фамилия и отчество. Далее идут "Петров Ольга", а потом ещё сотрудник Иванова это и фамилия и отчество.
Разделитель между сотрудниками должен быть другой. НЕ пробел.
Рекурсией можно сразу получать нужные пары. Но так писать в 29 не стал. Если что, то объяснять дольше.
(30) Если ФИ более 50 человек в строке, то рекурсия на MS SQL может не пройти (на SQLite проще там рекурсивный запрос и 300 вложенность глотает). На MS SQL и для более 50 человек есть решение, которое даже запрос 1С "смогёт", но не стоит. Там километровый запрос. Если данных много, то работает не быстро.
Далее у вас будет слова с номерами слов 1 и 2 их надо будет вместе соединить.
У STRING_SPLIT есть третий параметр. Он добавляет колонку с номером слова.
Можно рекурсией. Но есть ограничение. В MS SQL обычно стоит не более 100 вложенностей.
Под рукой сейчас только SQLite, но суть та же.
vt_data - ваши входные данные, но плюс пробел в конце строки. Пробел это у вас к сожалению разделитель.
vt - это обычный рекурсивный запрос разбивает на слова вашу строку
Итоговый собирает Фамилию+Имя по принципу четный и не четный: 1+2, 3+4, 5+6 и т.д.
WITH vt_data as
(SEL ECT t.f as f, t.str||' ' as str
FR OM
(SEL ECT 'Фирма 1' as f, 'Иван Петров Ольга Иванова' as str
UNI ON ALL SEL ECT 'Фирма 2', 'Петр Петров'
UNI ON ALL SELECT 'Фирма 3', 'Олег Иванов Петр Петров Анна Петрова'
) as t
)
, vt as
(SELECT
t.f
,substr(t.str, instr(t.str, ' ')+1) as str
,substr(t.str, 0, instr(t.str, ' ')) as slovo
,1 as npp
FR OM
vt_data as t
uni on ALL
SEL ECT
t.f
,substr(t.str, instr(t.str, ' ')+1)
,substr(t.str, 0, instr(t.str, ' '))
,t.npp + 1 as npp
FR OM vt as t
WH ERE instr(t.str, ' ')<>0
)
SEL ECT t.f as f, t.FI as FI
FR OM
(SEL ECT
t.f as f
,t.slovo || ' ' || LEAD(t.slovo) over(PARTITION by t.f ORDER by t.npp) as FI
,t.npp as npp
FR OM
vt as t
) as t
WH ERE t.npp%2<>0
ORDER by t.f, t.npp
Результат
f FI
Фирма 1 Иван Петров
Фирма 1 Ольга Иванова
Фирма 2 Петр Петров
Фирма 3 Олег Иванов
Фирма 3 Петр Петров
Фирма 3 Анна Петрова
(32)
нет... на самом деле проблема не в коде запроса... проблема в "среде"... я пытаюсь сделать запрос в PySpark, там немного другой синтаксис sql, и вот как раз на этой задаче не работает... пока не могу найти спеца по PySpark)
# Выбор одного столбца
data.sel ect('sector').show(5)
# Выбор нескольких столбцов
data.select(['open', 'close', 'adjusted']).show(5)
# Использование CASE WHEN в PySpark
sql = """
CASE
WHEN (lang LIKE 'c') OR (lang LIKE 'cpp') THEN 'C/C++'
WHEN (lang LIKE 'py') THEN 'Python'
ELSE 'unknown'
END"""
df.withColumn('FullLang', F.expr(sql)).show()
# Использование JOIN в PySpark
df.join(df2, df.name == df2.name, 'outer').select(df.name, df2.height).sort(desc("name")).show()
Показать
Этот вот так примерно будет в нем выглядеть рекурсивный запрос:
# Loop Through if you dont know recusrsive depth
while True:
this_level = 'level_{}'.format(i)
next_level = 'level_{}'.format(i+1)
emp_level = employees \
.withColumnRenamed('EMPLOYEE_NUMBER', this_level) \
.withColumnRenamed('MANAGER_EMPLOYEE_NUMBER', next_level)
empDF = empDF.join(emp_level, on=this_level, how='left')
# Check if DF is empty. Break loop if empty, Otherwise continue with next level
if empDF.where(col(next_level).isNotNull()).count() == 0:
break
else:
i += 1
# Sort columns and show
empDF.sort('level_0').select('level_0').show()
Показать
Извини, но это даже на SPARK SQL с точки зрения синтаксиса.
spark.sql("select lang fr om prog_info").show()
В pyspark это не запросы, а как в БСП набор каких-то функций работы с данными.
Pyspark больше похож на процедурную пошаговую работу с данными. С 1С можно сравнить как выгрузить всё в разные ТЗ и потом средствами БСП с этими данными что-то делать.
К формулировке в (1) "как это сделать при помощи запроса?", это не имеет никакого отношения.
Лучше скажи. Где эти данные физически лежат, как приходят, куда и в каком виде.
(50) (53) это просто рабочий вариант вместо того, что пытались сделать. То что пытались сделать не то и "это мне никак не поможет" без комментариев.
Просто поймите, что pyspark не поддерживает полное соответствие t-sql. Там "запрос" чем то напоминает его, но не полностью соответствует. И это вообще вторично там. В основном предполагается работа с объектной моделью данных. Вот это там очень мощный инструмент с лямбда выражениями.
Но не стоит напрямую натягивать язык t-sql на pyspark.
(55)все верно, я хотел решить в 2 этапа... сначала используя синтаксис sql (просто более понятен) а потом переписать на "родном" языке ps... но не могу в итоге даже сплит элементарный сделать(
(43)
1. Это разовая операция?
2. Чем обусловлено желание затащить данные, в том виде как они прилетают, и не возможность их предварительно переработать?
(44)
Ругается же не на STRING_SPLIT. Говорит что используйте JOIN.
(47) Куда затащили? Вы пытаетесь выполнить "не индуским" подходом, но не обращаете никакого внимания на текущие возможности вашей системы. Более того, скрываете до последнего, где и что вы делаете. :-) Что бы другие гадали, что и где вы делаете.
Если уже затащили и это разовая операция, тогда забудьте.
(50) Вы пытаетесь синтаксис MS SQL в чистом виде применить в другом синтаксисе.
Да все SQL языки очень сильно похожи, но не на столько же, что можно брать без адаптации код из одного и рисовать в другом.