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;
我有一个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;