Не удалось добавить ограничение WHERE на результат вложенного запроса - ОШИБКА 42883 в postgres - PullRequest
1 голос
/ 30 марта 2020

Мне кажется, что это довольно простой вложенный запрос, но, очевидно, я кое-что упускаю полностью.

НАСТРОЙКА:

  • У меня есть две таблицы ccod и psc.

  • psc имеет столбец company_number, с которым я хочу сопоставить

  • ccod.company_number_1 или ccod.company_number_2.

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

  • номера компаний не может быть пустым

  • номера компаний должны быть длиной 8 символов

  • psc.company_number чистые и содержат только строки длиной 8 символов.

  • ccod.company_number_1 или ccod.company_number_2 содержит много мусора.

  • ccod.company_number_1 или ccod.company_number_2 оба могут быть нулевыми, оба содержат строку или содержат одну.

  • Мне сейчас нет дела до дубликатов.

Плюс

  • Используйте UNION ALL, чтобы создать 1 отдельный столбец в результате объединения двух столбцов ccod - присвоить ему значение stacked_company_numbers .

так:

SELECT *
INTO ccod_psc
FROM psc
WHERE (SELECT DISTINCT psc.company_number)
          in
      (SELECT DISTINCT stacked_company_numbers
       FROM (SELECT company_number_1
             FROM ccod
             WHERE company_number_1 is not null
             UNION ALL
             SELECT company_number_2
             FROM ccod
             WHERE company_number_2 is not null) AS stacked_company_numbers
       WHERE char_length(stacked_company_numbers::text) = 8);
[42883] ERROR: operator does not exist: text = record
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
Position: 86

Теперь слова об этой ошибке довольно понятны, но я понятия не имею, как ее исправить, и попробовал Много других ответов, связанных с ошибкой 42883, но безуспешно.

Спасибо за любую помощь.

- РЕДАКТИРОВАТЬ:

Я также нашел способ заставить мой запрос работать:

SELECT *
INTO ccod_psc
FROM psc
WHERE (SELECT DISTINCT psc.company_number)
          in
      (SELECT company_number_1
       FROM ccod
       WHERE company_number_1 is not null
       UNION -- this takes cares of the duplicates.
       SELECT company_number_2
       FROM ccod
       WHERE company_number_2 is not null) AS stacked_company_numbers
WHERE char_length(stacked_company_numbers::text) = 8)

Ответы [ 2 ]

1 голос
/ 30 марта 2020

Я думаю, что два left join s более эффективны:

SELECT p.*
INTO ccod_psc c 
FROM psc p LEFT JOIN
     ccod c1
     ON p.company_number = c1.company_number_1 LEFT JOIN
     ccod c2
     ON p.company_number = c2.company_number_2 AND
        c1.company_number_1 IS NULL
WHERE c1.company_number_1 IS NOT NULL OR
      c2.company_number_2 IS NOT NULL 

Преимущество этого подхода состоит в том, что он может использовать индексы для ccod(company_number_1) и ccod(company_number_2).

EDIT :

Если в ccod могут быть дубликаты, тогда exists может иметь лучшую производительность:

SELECT p.*
INTO ccod_psc c 
FROM psc p
WHERE EXISTS (SELECT 1
              FROM ccod c1
              WHERE p.company_number = c1.company_number_1
             ) OR
     EXISTS (SELECT 1
              FROM ccod c2
              WHERE p.company_number = c2.company_number_2
             ) ;
1 голос
/ 30 марта 2020

Я подозреваю, что exists делает то, что вы хотите:

select p.*
from psc p
where 
    char_length(p.company_numbers::text) = 8
    and exists (
        select 1
        from ccod c
        where p.company_number in (c.company_number_1, c.company_number_2)
    )

Запрос извлекает записи из psc, чьи company_number имеют длину 8 символов и могут быть найдены либо в company_number_1 или company_number_2 в таблице ccod.

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