Postgres sql для выполнения соединения

Просто общий вопрос: может ли кто-нибудь помочь, как выполнить левое соединение для данных объединения. У меня есть запрос, в котором я объединяю данные (используя таблицу1 и таблицу2) на основе нескольких условий. Теперь мне нужно выполнить левое внешнее соединение с третьей таблицей (таблица5), поэтому я ищу помощь, как это сделать. Просто образец запроса подойдет.

Я создал сценарий на скрипке, где я выполнил объединение на основе нескольких условий, используя таблицу 1 и таблицу 2.https://dbfiddle.uk/WN6uC5MH Теперь мне нужно использовать выходные данные объединения и выполнить левое соединение для третьей таблицы, то есть таблицы 5. Поэтому мне нужно выполнить левое соединение в поле 6 таблицы 5 с выходным полем 1 данных объединения, если оно совпадает, а затем вставить строки в таблицу 5 со всеми значениями. останется прежним, за исключением поля 9, которое мы получим из выходных данных объединения (поле3):

Вывод будет выглядеть так:

'j','abc','def','xyz_inc'
'j','abc','def','5_abc'
'j','abc','def','6_abc'

Вы просто помещаете весь этот SQL в подзапрос и выполняете для него левое соединение. SELECT * FROM (<big union SELECT here>) as sub LEFT OUTER JOIN table3 ON sub.field1 = table3.field6;

JNevill 15.04.2024 21:18

@JNeville-Спасибо, что поделились, на самом деле я знаю этот синтаксис и пробовал, но в конце получаю ошибку, когда использую псевдоним после закрытия скобки. Можете ли вы помочь со скрипкой (dbfiddle.uk/WN6uC5MH), как это сделать, используя мой запрос?

Ram 15.04.2024 21:57

Поскольку вы уже используете CTE, я реорганизовал ваш запрос, а затем вместо того, чтобы полностью вставлять ваше объединение в подзапрос, я просто добавил новый CTE, который ссылается на два исходных. Затем в конце всех определений CTE мы можем выполнить соединение: dbfiddle.uk/U-P4vSpW

JNevill 15.04.2024 22:22
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
74
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Вы можете translate() один раз вместо того, чтобы звонить replace() дважды. Вы также можете объединить свои вызовы translate() вместо того, чтобы вкладывать их.
  2. Можно regexp_split_to_table() прямо вместо упаковки unnest(string_to_array()).
  3. Как отметил @JNevill, все, что вам нужно сделать, это вложить имеющийся у вас запрос либо в CTE, либо в подзапрос, а затем присоединиться к нему.

Демо на db<>fiddle:

with your_big_union as (
    select field1,field2,string_agg(distinct fld,',') field3
    from(
        select *
        from(
            select field1,field2,fld
            from table1 t1
            left join (
                select * from table2
                cross join regexp_split_to_table(trim(translate(field4,'{}','')),',') fld
              )t2
              on concat(t1.field2,';') similar to concat('%',t2.field3,'[();]%')
        )x
    )b
      where field2 like '%fn@_%' escape '@' and fld is not null
    group by field1,field2
    union
    (with cte as (
        select field1,field2
              ,''''
               ||translate( btrim(field2)
                            ,E'\n"'''
                            ,'' )
               ||''''  as edited_field2 
      from table1)
    ,cte2 as (
        select *,t.spotted_table as spotted_target,s.spotted_table as spotted_source
        from cte
        left join regexp_matches(
             edited_field2
            ,'(?:UPDATE|INTO)(?:\s+ONLY)?\s+([[:alpha:]_]+[\.\w]*|"[^"]+"(?:\."[^"]+")?)'
            ,'gi'
          ) with ordinality as target_matches(hits,n1) on true
      left join unnest(target_matches.hits) with ordinality as t(spotted_table,n2) on true
      left join   regexp_matches(
             edited_field2
            ,'(?:FROM|JOIN|USING|TABLE)(?:\s+ONLY)?\s+([[:alpha:]_]+[\.\w]*|"[^"]+"(?:\."[^"]+")?)'
            ,'gi'
          ) with ordinality as source_matches(hits,n1) on true
      left join unnest(source_matches.hits) with ordinality as s(spotted_table,n2) on true)
    select field1
          ,string_agg(distinct spotted_target,',') as spotted_targets
         -- ,string_agg(distinct spotted_source,',') as spotted_sources
          ,edited_field2
    from cte2 where edited_field2 not like '%fn@_%' escape '@' and spotted_target is not null
    and coalesce(split_part(spotted_target,'.',1) !~* '_inc"?$',true)
      and coalesce(split_part(spotted_source,'.',1) !~* '_inc"?$',true)
    group by field1,edited_field2
    order by field1))
select * 
from table5 left join your_big_union 
on lower(your_big_union.field1) = table5.field6;
  1. Если table5.field6 соединяется с field1, совпадений не будет, потому что вы написали 'J' в верхнем регистре в field, а field6 удерживает строчную. Я не понимаю, почему вы ожидаете 3 результата, если у вас есть только один 'j' с обеих сторон соединения.

Пример: dbfiddle.uk/sj8S5lK2 поэтому здесь мне не нужны строки таблицы «INC». Как это отфильтровать?

Ram 16.04.2024 14:15

@Ram Вы можете отфильтровать их точно так же, как и другой запрос: !~* '_inc"?$' и лучше всего сделать это перед агрегированием: демо. Если вы стремитесь агрегировать, а затем отключить вложение, возможно, будет проще array_agg(), а затем unnest() напрямую — меньше накладных расходов, более надежно и не заставляет вас дезинфицировать вещи на случай, если проскользнет дополнительный ,.

Zegarek 16.04.2024 16:46

Вопрос. Есть ли способ сравнить поле 3 с полем 9 после объединения, где вы в конце выбираете. dbfiddle.uk/MXhCQg5R. в основном в приведенном ниже запросе выбора: выберите * из таблицы 5 слева присоединиться к your_big_union на нижнем уровне (your_big_union.field1) = table5.field6; Я попытался сделать field3!=unnest(string_to_array(field9,',')) но он выдал ОШИБКУ: функции, возвращающие набор, не разрешены в условиях JOIN.

Ram 18.04.2024 15:59

Если бы вы использовали обычный array_agg(), это было бы тривиально field3<>all(field9), но вы все равно можете сделать field3!=all(string_to_array(field9,',')): демо. Я думаю, что в демо-версии поле3 содержит несколько значений, а поле9 — одно.

Zegarek 18.04.2024 16:40

@Zegarek-Большое спасибо. У меня есть пара вопросов, в некоторых местах у нас есть комментарии, которые также начинаются с ('--','/*'). Есть ли способ пропустить источник и цели для комментариев, поскольку это не так? необходимый. Я знаю, что синтаксический анализатор sql подойдет для этого лучше всего, но мне просто интересно найти обходной путь. Кроме того, в настоящее время в обнаруженных целях мы использовали регулярное выражение для INSERT и UPDATE... Есть ли способ включить регулярное выражение (Удалить из или Удалить * from). Я пробовал сохранить INSERT|UPDATE|DELETE таким образом, но он не работает должным образом. Я думаю, может быть, это связано с тем, что предложение FROM используется в источниках Spotted?

Ram 22.04.2024 10:47

@Ram Второе регулярное выражение ищет элементы FROM, поэтому оно должно найти идентификатор после DELETE FROM. Проблема в том, что он также выявляет источники UPDATE и INSERT, а не только их цели. Удаление/игнорирование конца строки --... и встроенных/многострочных комментариев /*...*/ можно обрабатывать как отдельное регулярное выражение. Я думаю, что время, которое вы уже потратили на изучение синтаксического анализа SQL на основе регулярных выражений, возможно, уже превысило то, что вам нужно было бы потратить на интеграцию SQLParse.

Zegarek 22.04.2024 11:08

@ Зегарек-верно, я посмотрю на это. Но я ценю твою помощь со сценарием.

Ram 22.04.2024 14:09

@Zegarek-for string_agg(distinct fld,',') ... Я получаю повторяющиеся значения. Пример: если у меня есть test3 дважды, я получаю test3, test3 ... Есть ли способ сохранить 1 значение вместо дубликата .

Ram 23.04.2024 21:38

@Ram distinct не может пропустить неразличимые значения. Вы либо добавляете дубликаты в другое место, либо упускаете из виду разницу в значениях, которые, по вашему мнению, являются повторяющимися. Проверьте конечные/начальные пробелы, разницу в регистре перед преобразованием в нижний регистр или проверьте, выглядят ли символы одинаково, но имеют ли они разные коды ascii/unicode: посмотрите эту демонстрацию.

Zegarek 23.04.2024 21:43

ох, извините, я имею в виду, что это строковые значения, такие как test,test, но они все равно получаются с разными значениями.

Ram 23.04.2024 21:45

Если фактическое значение строки равно test,test — два дубликата с разделителем/разделителем внутри, и именно так оно и поступает, то вы можете разделить, дедуплицировать и повторно агрегировать: demo. Еще раз: array_agg() всегда предпочтительнее.

Zegarek 23.04.2024 21:51

@Zegarek-Извиняюсь, я неправильно понял ваш последний комментарий... Вы молодцы, раньше были пробелы... Я использовал обрезку, чтобы удалить их, и теперь получаю ожидаемые значения :)

Ram 23.04.2024 21:59

Другие вопросы по теме