Отображать одну строку для каждого поискового запроса, если он не найден - PullRequest
1 голос
/ 14 ноября 2011

Запрос:

SELECT product_id,
       name 
  FROM product 
 WHERE barcode in (681027, 8901030349379,
                   679046, 679047,
                   679082, 679228,
                   679230, 679235,
                   679236, 679238,
                   679328, 679330,
                   679528, 679608,
                   679609, 679647,
                   679727, 679728,
                   679730, 679808,
                   679809, 679828, 679830)

Вывод:

YES   -IF PRODUCT NAME IS PRESENT
NO    -IF PRODUCT NAME IS NOT PRESENT
NO
YES
YES
NO
...                    

Как отобразить, если для определенного штрих-кода нет строки?Это хорошая практика для использования оператора IN в SQL?

Я использую PostgreSQL 8.2.11.

Ответы [ 2 ]

1 голос
/ 14 ноября 2011

Для PostgreSQL 8.4 +

Вы можете решить эту проблему с помощью unnest() и LEFT JOIN:

SELECT x.barcode
      ,p.product_id
      ,CASE WHEN p.name IS NULL THEN 'NO' ELSE 'YES' END AS product_name_exists
FROM   (SELECT unnest (
         '{679046,679047,679082,679228,679230,679235,679236,'
          '679238,679328,679330,679528,679608,679609,679647,'
          '679727,679728,679730,679808,679809,679828,679830}'::text[]) AS barcode
         ) x
LEFT   JOIN product USING (barcode);
  • unnest () генерирует одну строку на элемент ARRAY.Он был представлен в PostgreSQL 8.4.
  • LEFT JOIN обеспечивает отображение каждого barcode, даже если не найдено ни одного соответствующего продукта.

Будьте в курсеЭто может быть две причины отсутствия названия продукта: 1) Штрих-код не найден.2) product.name IS NULL.
Возможно, вы захотите добавить NOT NULL constraint к столбцу name в вашей таблице product - если у вас его нет.


Для PostgreSQL8.3

Используйте regexp_split_to_table ()

SELECT x.barcode
      ,p.product_id
      ,CASE WHEN p.name IS NULL THEN 'NO' ELSE 'YES' END AS product_name_exists
FROM   (SELECT regexp_split_to_table (
              '679046,679047,679082,679228,679230,679235,679236,'
              '679238,679328,679330,679528,679608,679609,679647,'
              '679727,679728,679730,679808,679809,679828,679830', ',') AS barcode
         ) x
LEFT   JOIN product USING (barcode);
  • Альтернативой будет regexp_split_to_table () , представленная в PostgreSQL 8.3.
  • Обратите внимание, какчасти строки объединяются автоматически.Не очень известная функция, определенная стандартом SQL.

Для PostgreSQL 8.2

Пока не существует ни одной из функций, генерирующих SET. Рассмотрите возможность обновления до более новой версии!PostgreSQL 8.2 достигает конца срока службы в декабре 2011 года .

Универсальное решение для любого количества штрих-кодов (медленно для очень большого числа штрих-кодов):

SELECT x.barcode
      ,p.product_id
      ,CASE WHEN p.name IS NULL THEN 'NO' ELSE 'YES' END AS product_name_exists
FROM (
    SELECT a[i] AS barcode
    FROM   (
        SELECT a.a, generate_series(1, array_upper(a.a, 1)) AS i
        FROM   ( 
            SELECT
            '{679046,679047,679082,679228,679230,679235,679236,'
             '679238,679328,679330,679528,679608,679609,679647,'
             '679727,679728,679730,679808,679809,679828,679830}'::text[] AS a
            ) a
        ) i
    )x
LEFT   JOIN product USING (barcode);

Или явная конструкция SET с UNION ALL:

SELECT x.barcode
      ,p.product_id
      ,CASE WHEN p.name IS NULL THEN 'NO' ELSE 'YES' END AS product_name_exists
FROM (
    SELECT           '679046' AS barcode
    UNION ALL SELECT '679047'
    UNION ALL SELECT '679082'
    UNION ALL SELECT '679228'
    UNION ALL SELECT '679230'
    UNION ALL SELECT '679235'
    UNION ALL SELECT '679236'
-- ...
    ) x
LEFT   JOIN product USING (barcode);
1 голос
/ 14 ноября 2011

Это может сработать:

select case when p.name is null then 'NO' else 'YES' end as barcode_exists, t.barcode
from product as p
right join (
    select 681027 as barcode union
    select 8901030349379 union
    select 679046 union
    select 679047 union
    select 679082 union
    select 679228 union
    select 679230 union
    select 679235 union
    select 679236 union
    select 679238 union
    select 679328 union
    select 679330 union
    select 679528 union
    select 679608
            -- all the rest barcodes
) as t on p.barcode = t.barcode

В union введите все штрих-коды, которые вы хотите проверить.

Aded:

Возвращает два столбца для сопоставления штрих-кода и ответ , поскольку вы не можете ретранслировать порядок строк, если не укажете один.

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