如何取消透视多列并从任一列中排除值?

How can I unpivot multiple columns and exclude values from either column?

我有一个 table,其中包含一个 id 和两个产品列,productproduct_otherproduct 列可能有一个有效的产品名称,单词 "other",或者是空白,因为它来自源。如果 product 为 "other",则 product_other 应具有有效的产品名称,否则可能为空或随机包含有效的产品名称。 我需要将所有有效的产品名称拉到一个列中,并排除空白和 "other" 条目。到目前为止,我已经尝试了两种方法,UNION 方法如下:

SELECT DISTINCT * FROM
(
    SELECT id
        , COALESCE(NULLIF(NULLIF(product, 'other'), ''), 'UNKNOWN') AS product
    FROM myTable
    UNION
    SELECT id
        , COALESCE(NULLIF(product_other, ''), 'UNKNOWN') AS product
    FROM myTable
) k
ORDER BY id

这会生成所有行,包括 product 的 'UNKNOWN' 值和相同 idproduct_other 的有效产品名称,而它应该只提供有效名称如果有的话。

我使用的另一种方法是下面的 CASE WHEN 方法:

SELECT id
    , CASE COALESCE(NULLIF(product, ''), 'UNKNOWN')
            WHEN 'other' THEN COALESCE(NULLIF(product_other, ''), 'UNKNOWN')
            ELSE COALESCE(NULLIF(product_other, ''), 'UNKNOWN')
        END AS product
FROM myTable
ORDER BY id

但是,这个只生成了可用的有效 product 列表,或者当 product 为 "other" 或空白时生成了 product_other 列表。它排除了存在有效 product productproduct_other 值的情况的可能性。

另一种看待它的方法是,如果您 SELECT id, count(*) FROM ( 以 k ) GROUP BY id 查询,第一种情况下会有计数为 2 的行,无论一个是 "UNKNOWN"或不,第二个总是每个 id.

只有 1 行

所以,myTable 看起来像这样:

id      product     product_other
------  ---------   ---------------
155535  OTC         COM
155536              OTC
155537  other       COM
155538  

我希望查询结果如下所示:

id      product
------  ---------
155535  OTC
155535  COM
155536  OTC
155537  COM
155538  UNKNOWN

谢谢。

试试这个:

    CREATE TABLE #temp (id   int ,   product  varchar(10),    product_other VARCHAR(10))


    INSERT INTO #temp 
    VALUES(155535,'OTC','COM'),
    (155536, '' ,'OTC'),
    (155537,'other','COM'),
    (155538,'','') 

SELECT id
    , CASE  WHEN  COALESCE(NULLIF(product, ''),NULLIF(product_other, ''))  = 'other' AND NULLIF(product_other, '') IS NOT NULL  THEN product_other
           WHEN   COALESCE(NULLIF(product, ''),NULLIF(product_other, '')) IS NULL AND  NULLIF(product_other, '') IS NULL  THEN  'UNKNOWN' 
           ELSE  COALESCE(NULLIF(product, ''),NULLIF(product_other, '')) END  AS product 
FROM #temp
UNION
SELECT id
    ,CASE  WHEN  COALESCE(NULLIF(product_other, ''),NULLIF(product, ''))  = 'other' AND NULLIF(product, '') IS NOT NULL  THEN product_other
           WHEN   COALESCE(NULLIF(product_other, ''),NULLIF(product, '')) IS NULL AND  NULLIF(product, '') IS NULL  THEN  'UNKNOWN' 
           ELSE  COALESCE(NULLIF(product_other, ''),NULLIF(product, '')) END  AS product 
FROM #temp;

结果:

所以本质上是这样的逻辑:

SELECT id
    , CASE  WHEN  COALESCE(NULLIF(product, ''),NULLIF(product_other, ''))  = 'other' AND NULLIF(product_other, '') IS NOT NULL  THEN product_other
           WHEN   COALESCE(NULLIF(product, ''),NULLIF(product_other, '')) IS NULL AND  NULLIF(product_other, '') IS NULL  THEN  'UNKNOWN' 
           ELSE  COALESCE(NULLIF(product, ''),NULLIF(product_other, '')) END  AS product 
FROM myTable
UNION
SELECT id
    ,CASE  WHEN  COALESCE(NULLIF(product_other, ''),NULLIF(product, ''))  = 'other' AND NULLIF(product, '') IS NOT NULL  THEN product_other
           WHEN   COALESCE(NULLIF(product_other, ''),NULLIF(product, '')) IS NULL AND  NULLIF(product, '') IS NULL  THEN  'UNKNOWN' 
           ELSE  COALESCE(NULLIF(product_other, ''),NULLIF(product, '')) END  AS product 
FROM myTable;
SELECT *
FROM myTable
UNPIVOT(product_name FOR product_type IN (product, product_other)) u
WHERE
    u.product_name NOT IN ('', 'other');

SQLFiddle