我没有深刻的SQL背景,最近遇到的SQL问题似乎很难用JUST SQL。
我有一张桌子
```
IMEI | DATE | A_1 | A_2 | A_3 | B_1 | B_2 | B_3
2132 | 09/21| 2 | 4 | 4 | 5 | 2 | 4
4535 | 09/22| 2 | 2 | 4 | 5 | 2 | 3
9023 | 09/21| 2 | 1 | 5 | 7 | 2 | 2
```
如何以某种方式对A_1
,A_2
等的值进行分组,以便我可以实现此表。基本上,我想在表格中对某些列进行分组,并将它们放入不同的行中。
IMEI | DATE | MODULE | val_1 | val_2 | val_3
2132 | 09/21| A | 2 | 4 | 4
2132 | 09/21| B | 5 | 2 | 4
...
目标是在名称空间A
,B
等下获取值,以便将行分成新表中的不同行。
此外,有关我在哪里可以改进我的SQL的任何建议。我应该保留哪些书作为参考或我应该使用的任何其他资源?
谢谢!
答案 0 :(得分:3)
您可以使用UNION
:
SELECT IMEI, DATE, 'A' AS MODULE, A_1 AS val_1, A_2 AS val_2, A_3 AS val_3
FROM myTable
UNION ALL
SELECT IMEI, DATE, 'B', B_1, B_2, B_3
FROM myTable
在sqlfiddle上查看。
但实际上,您应该将数据存储在上述查询创建的表单中,然后使用JOIN
在需要时创建原始格式。
答案 1 :(得分:2)
我喜欢玩这样的数据和问题!
以下可以被认为是过度工程,但我认为,如果您事先不知道您的列名,但有一个您描述的模式,或者它只是用于学习,看起来像您正在寻找改进你的SQL(基于这个问题的标记我假设你的意思是BigQuery SQL)
#standardSQL
WITH parsed AS (
SELECT IMEI, DATE,
REGEXP_REPLACE(SPLIT(row, ':')[OFFSET(0)], r'^"|"$', '') key,
REGEXP_REPLACE(SPLIT(row, ':')[OFFSET(1)], r'^"|"$', '') value
FROM `yourTable` t,
UNNEST(SPLIT(REGEXP_REPLACE(to_json_string(t), r'[{}]', ''))) row
),
grouped AS (
SELECT
IMEI, DATE,
REGEXP_EXTRACT(key, r'(.*)_') MODULE,
ARRAY_AGG(value ORDER BY CAST(REGEXP_EXTRACT(key, r'_(.*)') AS INT64)) AS vals
FROM parsed
WHERE key NOT IN ('IMEI', 'DATE')
GROUP BY IMEI, DATE, MODULE
)
SELECT IMEI, DATE, MODULE,
vals[SAFE_OFFSET(0)] AS val_1,
vals[SAFE_OFFSET(1)] AS val_2,
vals[SAFE_OFFSET(2)] AS val_3,
vals[SAFE_OFFSET(3)] AS val_4
FROM grouped
-- ORDER BY IMEI, DATE, MODULE
您可以使用问题中的虚拟数据进行测试/播放
#standardSQL
WITH `yourTable` AS (
SELECT 2132 IMEI, '09/21' DATE, 2 A_1, 4 A_2, 4 A_3, 5 B_1, 2 B_2, 4 B_3 UNION ALL
SELECT 4535, '09/22', 2, 2 ,4, 5, 2, 3 UNION ALL
SELECT 9023, '09/21', 2, 1 ,5, 7, 2, 2
),
parsed AS (
SELECT IMEI, DATE,
REGEXP_REPLACE(SPLIT(row, ':')[OFFSET(0)], r'^"|"$', '') key,
REGEXP_REPLACE(SPLIT(row, ':')[OFFSET(1)], r'^"|"$', '') value
FROM `yourTable` t,
UNNEST(SPLIT(REGEXP_REPLACE(to_json_string(t), r'[{}]', ''))) row
),
grouped AS (
SELECT
IMEI, DATE,
REGEXP_EXTRACT(key, r'(.*)_') MODULE,
ARRAY_AGG(value ORDER BY CAST(REGEXP_EXTRACT(key, r'_(.*)') AS INT64)) AS vals
FROM parsed
WHERE key NOT IN ('IMEI', 'DATE')
GROUP BY IMEI, DATE, MODULE
)
SELECT IMEI, DATE, MODULE,
vals[SAFE_OFFSET(0)] AS val_1,
vals[SAFE_OFFSET(1)] AS val_2,
vals[SAFE_OFFSET(2)] AS val_3,
vals[SAFE_OFFSET(3)] AS val_4
FROM grouped
ORDER BY IMEI, DATE, MODULE
输出如下
Row IMEI DATE MODULE val_1 val_2 val_3 val_4
1 2132 09/21 A 2 4 4 null
2 2132 09/21 B 5 2 4 null
3 4535 09/22 A 2 2 4 null
4 4535 09/22 B 5 2 3 null
5 9023 09/21 A 2 1 5 null
6 9023 09/21 B 7 2 2 null