我需要从表中获取最大记录数,并将该数字连接到字段名称的末尾,从 1 开始到最大记录数结束:
字段1 | cnt |
---|---|
汽车 | 4 |
卡车 | 3 |
最终结果需要以以下格式导出:
Car|1
Car|2
Car|3
Car|4
Truck|1
Truck|2
Truck|3
我不能使用
RAISE
,因为在这种情况下我需要的不仅仅是一条消息。它必须是数据输出,以便结果可以在下游使用。
如果那是你的桌子(符合你的描述):
CREATE TABLE tbl1 (
tbl_id serial PRIMARY KEY
, field1 text
);
然后
row_number()
作品:
SELECT field1 || '|' || row_number() OVER (PARTITION BY field1)
FROM tbl1;
如果那是你的表(你的样本数据):
CREATE TABLE tbl2 (
tbl_id serial PRIMARY KEY
, field1 text
, cnt int
);
然后
generate_series()
完成工作:
SELECT field1 || '|' || g
FROM tbl2, generate_series(1, cnt) g;
无论哪种方式都不需要循环和递归。
以下是实现上述结果的两种方法。第一个使用递归公用表表达式 (CTE),非常类似于过程语言中的循环。使用数据库时,摆脱过程性思维并采用基于集合的方法是很有用的。第二个查询中演示了基于集合的方法。
WITH RECURSIVE parms(field1, cnt) AS (
VALUES ('Car', 4),
('Truck', 3)
),
cte(field1, cnt, n) AS (
SELECT parms.field1, parms.cnt, 1 AS n
FROM parms
WHERE parms.cnt > 0
UNION ALL
SELECT cte.field1, cte.cnt, cte.n + 1 AS n
FROM cte
WHERE cte.n < cte.cnt
)
SELECT cte.field1 || '|' || cte.n::text AS result
FROM cte
ORDER BY cte.field1, cte.n;
WITH parms(field1, cnt) AS (
VALUES ('Car', 4),
('Truck', 3)
),
c AS (
SELECT generate_series(1, MAX(parms.cnt)) AS n
FROM parms
)
SELECT parms.field1 || '|' || c.n::text AS result
FROM parms
JOIN c ON c.n <= parms.cnt
ORDER BY parms.field1, c.n;