通过查找 Table 替换 SQL 中的列值
Replace Column Values in SQL from a lookup Table
我有一个 sql Employee
Table 描述了用户对特定金属的喜爱程度,table 看起来像这样
"Employee_number" "Rank_1 "Rank_2 "Rank_3 "Rank_4 "Rank5
1 Gold null null null null
2 bronze Gold null null null
3 Gold platinum null null null
4 Gold copper null null null
5 Gold bronze platinum null null
6 Gold bronze platinum null null
7 Gold platinum Silver null null
8 Gold platinum Silver null null
9 Gold platinum business null null
10 null null null null null
11 Silver bronze business platinum Gold
Employee_number字段是唯一字段,
还有一个table描述了金属的一般排名,它看起来像这样:
Metal Rank
Gold 1
platinum 2
silver 3
copper 4
bronze 5
我想做的是,每当员工有空值时,根据他们的排名填写默认金属
例如 -> 对于员工 10:所有值均为空,简单,他的 rank_1 金属将是黄金,rank2_metal 将是白金,rank3_metal 将是白银,排名 4_metal 将是铜牌,排名 5_metal 将是青铜牌
现在 employee_1,他已经有了 rank_1 金属,但没有其他等级可用,所以用白金替换 rank2_metal,用银替换 rank_3 金属, rank_4 金属与铜,rank_5 金属与青铜
现在 employee_2,他的第一金属是青铜,第二金属是金,他的 rank3_metal 是白金,rank_4 金属是银,排名5_metal 将是铜
相似,让我们以 employee_6 的情况为例,他已经填充了三个等级,需要填充等级 4 和 5,他的 rank_4 金属将是银,而 rank_5 金属将是铜
有没有人对 sql 中的一个有任何建议,我正在使用 bigquery
以下适用于 BigQuery 标准 SQL - 希望您将其用于您的实际用例。
#standardSQL
WITH metals AS (
SELECT 'Gold' Metal, 1 RANK UNION ALL SELECT 'platinum', 2 UNION ALL
SELECT 'silver', 3 UNION ALL SELECT 'copper', 4 UNION ALL SELECT 'bronze', 5
)
SELECT Employee_number,
MAX(IF(pos=0, Metal, NULL)) Rank_1,
MAX(IF(pos=1, Metal, NULL)) Rank_2,
MAX(IF(pos=2, Metal, NULL)) Rank_3,
MAX(IF(pos=3, Metal, NULL)) Rank_4,
MAX(IF(pos=4, Metal, NULL)) Rank_5
FROM (
SELECT Employee_number,
ARRAY_CONCAT(
ARRAY(SELECT Metal FROM (
SELECT 1 a, Rank_1 Metal UNION ALL SELECT 2, Rank_2 UNION ALL
SELECT 3, Rank_3 UNION ALL SELECT 4, Rank_4 UNION ALL
SELECT 5, Rank_5 )
WHERE NOT Metal IS NULL
ORDER BY a
), ARRAY(SELECT Metal FROM metals m
WHERE NOT LOWER(Metal) IN (
SELECT x FROM UNNEST(ARRAY(
SELECT LOWER(b) FROM (
SELECT Rank_1 b UNION ALL SELECT Rank_2 UNION ALL
SELECT Rank_3 UNION ALL SELECT Rank_4 UNION ALL
SELECT Rank_5 )
WHERE NOT b IS NULL
)) x
) ORDER BY RANK
)) arr
FROM `project.dataset.employee`
), UNNEST(arr) Metal WITH OFFSET pos
GROUP BY Employee_number
ORDER BY Employee_number
您可以使用您问题中的虚拟数据进行测试,如下所示
#standardSQL
WITH `project.dataset.employee` AS (
SELECT 1 Employee_number, 'Gold' Rank_1, NULL Rank_2, NULL Rank_3, NULL Rank_4, NULL Rank_5 UNION ALL
SELECT 2, 'bronze', 'Gold', NULL, NULL, NULL UNION ALL
SELECT 3, 'Gold', 'platinum', NULL, NULL, NULL UNION ALL
SELECT 4, 'Gold', 'copper', NULL, NULL, NULL UNION ALL
SELECT 5, 'Gold', 'bronze', 'platinum', NULL, NULL UNION ALL
SELECT 6, 'Gold', 'bronze', 'platinum', NULL, NULL UNION ALL
SELECT 7, 'Gold', 'platinum', 'Silver', NULL, NULL UNION ALL
SELECT 8, 'Gold', 'platinum', 'Silver', NULL, NULL UNION ALL
SELECT 9, 'Gold', 'platinum', 'business', NULL, NULL UNION ALL
SELECT 10, NULL, NULL, NULL, NULL, NULL UNION ALL
SELECT 11, 'Silver', 'bronze', 'business', 'platinum', 'Gold'
), metals AS (
SELECT 'Gold' Metal, 1 RANK UNION ALL SELECT 'platinum', 2 UNION ALL
SELECT 'silver', 3 UNION ALL SELECT 'copper', 4 UNION ALL SELECT 'bronze', 5
)
SELECT Employee_number,
MAX(IF(pos=0, Metal, NULL)) Rank_1,
MAX(IF(pos=1, Metal, NULL)) Rank_2,
MAX(IF(pos=2, Metal, NULL)) Rank_3,
MAX(IF(pos=3, Metal, NULL)) Rank_4,
MAX(IF(pos=4, Metal, NULL)) Rank_5
FROM (
SELECT Employee_number,
ARRAY_CONCAT(
ARRAY(SELECT Metal FROM (
SELECT 1 a, Rank_1 Metal UNION ALL SELECT 2, Rank_2 UNION ALL
SELECT 3, Rank_3 UNION ALL SELECT 4, Rank_4 UNION ALL
SELECT 5, Rank_5 )
WHERE NOT Metal IS NULL
ORDER BY a
), ARRAY(SELECT Metal FROM metals m
WHERE NOT LOWER(Metal) IN (
SELECT x FROM UNNEST(ARRAY(
SELECT LOWER(b) FROM (
SELECT Rank_1 b UNION ALL SELECT Rank_2 UNION ALL
SELECT Rank_3 UNION ALL SELECT Rank_4 UNION ALL
SELECT Rank_5 )
WHERE NOT b IS NULL
)) x
) ORDER BY RANK
)) arr
FROM `project.dataset.employee`
), UNNEST(arr) Metal WITH OFFSET pos
GROUP BY Employee_number
ORDER BY Employee_number
结果
Row Employee_number Rank_1 Rank_2 Rank_3 Rank_4 Rank_5
1 1 Gold platinum silver copper bronze
2 2 bronze Gold platinum silver copper
3 3 Gold platinum silver copper bronze
4 4 Gold copper platinum silver bronze
5 5 Gold bronze platinum silver copper
6 6 Gold bronze platinum silver copper
7 7 Gold platinum Silver copper bronze
8 8 Gold platinum Silver copper bronze
9 9 Gold platinum business silver copper
10 10 Gold platinum silver copper bronze
11 11 Silver bronze business platinum Gold
注意:以上解决方案假设填充金属和 NULL 金属之间没有混合,这意味着三个选项:
1. all Rank fields filled already with Metal
2. all Rank fields are NULL
3. first 1 or more fields filled with Metal and rest are NULLs
话虽如此,第一个数组是由填充字段构成的;第二个数组由 Metals table 的其余 Metal 字段构建而成;然后连接两个数组,前 5 个元素用于重新创建原始 table
希望不要太乱
P.S。上面的解决方案可以相对容易地扩展到 NULL 和填充金属混合使用的情况 - 但看起来这超出了问题的范围 :o)
我有一个 sql Employee
Table 描述了用户对特定金属的喜爱程度,table 看起来像这样
"Employee_number" "Rank_1 "Rank_2 "Rank_3 "Rank_4 "Rank5
1 Gold null null null null
2 bronze Gold null null null
3 Gold platinum null null null
4 Gold copper null null null
5 Gold bronze platinum null null
6 Gold bronze platinum null null
7 Gold platinum Silver null null
8 Gold platinum Silver null null
9 Gold platinum business null null
10 null null null null null
11 Silver bronze business platinum Gold
Employee_number字段是唯一字段,
还有一个table描述了金属的一般排名,它看起来像这样:
Metal Rank
Gold 1
platinum 2
silver 3
copper 4
bronze 5
我想做的是,每当员工有空值时,根据他们的排名填写默认金属
例如 -> 对于员工 10:所有值均为空,简单,他的 rank_1 金属将是黄金,rank2_metal 将是白金,rank3_metal 将是白银,排名 4_metal 将是铜牌,排名 5_metal 将是青铜牌
现在 employee_1,他已经有了 rank_1 金属,但没有其他等级可用,所以用白金替换 rank2_metal,用银替换 rank_3 金属, rank_4 金属与铜,rank_5 金属与青铜
现在 employee_2,他的第一金属是青铜,第二金属是金,他的 rank3_metal 是白金,rank_4 金属是银,排名5_metal 将是铜
相似,让我们以 employee_6 的情况为例,他已经填充了三个等级,需要填充等级 4 和 5,他的 rank_4 金属将是银,而 rank_5 金属将是铜
有没有人对 sql 中的一个有任何建议,我正在使用 bigquery
以下适用于 BigQuery 标准 SQL - 希望您将其用于您的实际用例。
#standardSQL
WITH metals AS (
SELECT 'Gold' Metal, 1 RANK UNION ALL SELECT 'platinum', 2 UNION ALL
SELECT 'silver', 3 UNION ALL SELECT 'copper', 4 UNION ALL SELECT 'bronze', 5
)
SELECT Employee_number,
MAX(IF(pos=0, Metal, NULL)) Rank_1,
MAX(IF(pos=1, Metal, NULL)) Rank_2,
MAX(IF(pos=2, Metal, NULL)) Rank_3,
MAX(IF(pos=3, Metal, NULL)) Rank_4,
MAX(IF(pos=4, Metal, NULL)) Rank_5
FROM (
SELECT Employee_number,
ARRAY_CONCAT(
ARRAY(SELECT Metal FROM (
SELECT 1 a, Rank_1 Metal UNION ALL SELECT 2, Rank_2 UNION ALL
SELECT 3, Rank_3 UNION ALL SELECT 4, Rank_4 UNION ALL
SELECT 5, Rank_5 )
WHERE NOT Metal IS NULL
ORDER BY a
), ARRAY(SELECT Metal FROM metals m
WHERE NOT LOWER(Metal) IN (
SELECT x FROM UNNEST(ARRAY(
SELECT LOWER(b) FROM (
SELECT Rank_1 b UNION ALL SELECT Rank_2 UNION ALL
SELECT Rank_3 UNION ALL SELECT Rank_4 UNION ALL
SELECT Rank_5 )
WHERE NOT b IS NULL
)) x
) ORDER BY RANK
)) arr
FROM `project.dataset.employee`
), UNNEST(arr) Metal WITH OFFSET pos
GROUP BY Employee_number
ORDER BY Employee_number
您可以使用您问题中的虚拟数据进行测试,如下所示
#standardSQL
WITH `project.dataset.employee` AS (
SELECT 1 Employee_number, 'Gold' Rank_1, NULL Rank_2, NULL Rank_3, NULL Rank_4, NULL Rank_5 UNION ALL
SELECT 2, 'bronze', 'Gold', NULL, NULL, NULL UNION ALL
SELECT 3, 'Gold', 'platinum', NULL, NULL, NULL UNION ALL
SELECT 4, 'Gold', 'copper', NULL, NULL, NULL UNION ALL
SELECT 5, 'Gold', 'bronze', 'platinum', NULL, NULL UNION ALL
SELECT 6, 'Gold', 'bronze', 'platinum', NULL, NULL UNION ALL
SELECT 7, 'Gold', 'platinum', 'Silver', NULL, NULL UNION ALL
SELECT 8, 'Gold', 'platinum', 'Silver', NULL, NULL UNION ALL
SELECT 9, 'Gold', 'platinum', 'business', NULL, NULL UNION ALL
SELECT 10, NULL, NULL, NULL, NULL, NULL UNION ALL
SELECT 11, 'Silver', 'bronze', 'business', 'platinum', 'Gold'
), metals AS (
SELECT 'Gold' Metal, 1 RANK UNION ALL SELECT 'platinum', 2 UNION ALL
SELECT 'silver', 3 UNION ALL SELECT 'copper', 4 UNION ALL SELECT 'bronze', 5
)
SELECT Employee_number,
MAX(IF(pos=0, Metal, NULL)) Rank_1,
MAX(IF(pos=1, Metal, NULL)) Rank_2,
MAX(IF(pos=2, Metal, NULL)) Rank_3,
MAX(IF(pos=3, Metal, NULL)) Rank_4,
MAX(IF(pos=4, Metal, NULL)) Rank_5
FROM (
SELECT Employee_number,
ARRAY_CONCAT(
ARRAY(SELECT Metal FROM (
SELECT 1 a, Rank_1 Metal UNION ALL SELECT 2, Rank_2 UNION ALL
SELECT 3, Rank_3 UNION ALL SELECT 4, Rank_4 UNION ALL
SELECT 5, Rank_5 )
WHERE NOT Metal IS NULL
ORDER BY a
), ARRAY(SELECT Metal FROM metals m
WHERE NOT LOWER(Metal) IN (
SELECT x FROM UNNEST(ARRAY(
SELECT LOWER(b) FROM (
SELECT Rank_1 b UNION ALL SELECT Rank_2 UNION ALL
SELECT Rank_3 UNION ALL SELECT Rank_4 UNION ALL
SELECT Rank_5 )
WHERE NOT b IS NULL
)) x
) ORDER BY RANK
)) arr
FROM `project.dataset.employee`
), UNNEST(arr) Metal WITH OFFSET pos
GROUP BY Employee_number
ORDER BY Employee_number
结果
Row Employee_number Rank_1 Rank_2 Rank_3 Rank_4 Rank_5
1 1 Gold platinum silver copper bronze
2 2 bronze Gold platinum silver copper
3 3 Gold platinum silver copper bronze
4 4 Gold copper platinum silver bronze
5 5 Gold bronze platinum silver copper
6 6 Gold bronze platinum silver copper
7 7 Gold platinum Silver copper bronze
8 8 Gold platinum Silver copper bronze
9 9 Gold platinum business silver copper
10 10 Gold platinum silver copper bronze
11 11 Silver bronze business platinum Gold
注意:以上解决方案假设填充金属和 NULL 金属之间没有混合,这意味着三个选项:
1. all Rank fields filled already with Metal
2. all Rank fields are NULL
3. first 1 or more fields filled with Metal and rest are NULLs
话虽如此,第一个数组是由填充字段构成的;第二个数组由 Metals table 的其余 Metal 字段构建而成;然后连接两个数组,前 5 个元素用于重新创建原始 table
希望不要太乱
P.S。上面的解决方案可以相对容易地扩展到 NULL 和填充金属混合使用的情况 - 但看起来这超出了问题的范围 :o)