GROUP BY 如果不为空则取给定值

GROUP BY and take the given value if it is not empty

我有一个table

+-----+-----------+-----+
| ID  | NAME      | LOC |
+-----+-----------+-----+
| 101 | Stainless | NY  |
| 101 | Brass     | MUM |
| 102 |           | NY  |
| 102 | Gold      | JP  |
| 103 | Silver    | CN  |
| 103 | Aluminium | US  |
| 104 | Platinum  | NY  |
| 104 | Diamond   | UK  |
| 105 |           | NY  |
+-----+-----------+-----+

我想group by并取NAME对应的NY位置。如果 NAME 对于 NY 为空,则取另一个。如果 NY 不适用于任何 ID,则从其他位置获取任何 NAME。如果某个 ID 只出现一次且为空 NAME,那么我们可以采用相同的方法。

预期输出

+-----+-----------+
| ID  | NAME      |
+-----+-----------+
| 101 | Stainless |
| 102 | Gold      |
| 103 | Silver    |
| 104 | Platinum  |
| 105 |           |
+-----+-----------+

我试过下面的查询。但它没有给出我预期的输出。我错过了什么?

SELECT ID, MAX(CASE WHEN LOC='NY' AND NAME!='' THEN NAME END) NAME
FROM MYTABLE  
GROUP BY ID

您可以使用 row_number() - DEMO HERE

select * from
(
SELECT *,
row_number() over(partition by id order by case when NAME='' then -1 when LOC='NY' AND NAME!='' then 1 else 0 end desc) as rn
FROM t 
)A where rn=1

请在依赖给定脚本之前进行全面测试,因为它基于给定的微小数据样本。

SELECT ID, NAME, LOC
FROM (
    SELECT *, ROW_NUMBER() OVER (
            PARTITION BY ID ORDER BY ID
            ) AS run
    FROM Table_1
    WHERE ID NOT IN (
            SELECT ID
            FROM Table_1
            WHERE LOC = 'NY' AND Name IS NOT NULL
            ) AND NAME IS NOT NULL
    ) A
WHERE run = 1

UNION ALL

SELECT *
FROM Table_1
WHERE LOC = 'NY' AND Name IS NOT NULL
ORDER BY ID

您可以像这样使用聚合:

select id,
       coalesce( max(case when location = 'NY' then name end),
                 max(name)
               ) as desired_name
from t
group by id;

注意:这假定空白名称确实是 NULL。如果不是,则调整逻辑:

select id,
       coalesce( max(case when location = 'NY' and name <> '' then name end),
                 max(name)
               ) as desired_name
from t
group by id;