每个搜索词显示一行,如果未找到则替换默认值

时间:2011-11-14 05:04:55

标签: mysql postgresql

查询:

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
...                    

如果特定条形码没有行,我该如何显示?在sql中使用IN语句是一种好习惯吗?

我使用PostgreSQL 8.2.11。

2 个答案:

答案 0 :(得分:1)

这可能有效:

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中输入您要检查的所有条形码。

<强>交锋:

它会返回两列以匹配条形码和回答,因为除非您指定一行,否则无法按行顺序进行中继。

答案 1 :(得分:1)

对于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 - 如果您没有。{/ p>


对于PostgreSQL 8.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正在达到end of life in Dezember 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);

使用UNION ALL进行显式SET构建:

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);