我知道我可能只是在考虑这个错误。我有以下结构:
CREATE TABLE mytable (
id serial PRIMARY KEY
, employee text UNIQUE NOT NULL
, data jsonb
);
以下数据:
INSERT INTO mytable (employee, data)
VALUES
('Jim', '{"sales": [{"value": 10, "yr": "2010"}, {"value": 5, "yr": "2011"}, {"value": 40, "yr": "2012"}]}'),
('Rob', '{"sales": [{"value": 10, "yr": "2009"}, {"value": 5, "yr": "2010"}, {"value": 41, "yr": "2011"}]}')
我试图归还所有员工和"价值"他们在2012年的销售情况。如果2012年没有销售,则返回"无数据"。我有:
SELECT id, employee,
coalesce((SELECT s.value AS value FROM mytable, jsonb_to_recordset(mytable.data->'sales') AS s(yr text, value float)
WHERE s.yr='2012'), 0) AS b FROM mytable
我明白了:
id |employee |b
53 |Jim |40
54 |Rob |40
Rob'价值是错误的。它应该是“无数据”。 (我使用0作为合并的第二个参数,因为我收到错误"类型双精度的输入语法无效:'没有数据'"
答案 0 :(得分:0)
问题是您的内部 SELECT
实际上并未过滤员工的ID。因此,吉姆的40也被选为罗布。
实际上,如果您插入另一名具有2012年值的员工,实际上要容易得多 你会得到
ERROR: 21000: more than one row returned by a subquery used as an expression
因为SELECT value FROM ... WHERE yr = '2012'
会返回多个值,即您(基本上)会要求(假设第二个员工有41个销售额)
SELECT COALESCE((VALUES (40), (41)));
您可以使用CTE(可能不是最有效的方式):
WITH sales_2012 AS (
SELECT id, s.value
FROM mytable,
jsonb_to_recordset(mytable.data->'sales') AS s(yr text, value float)
WHERE s.yr='2012'
)
SELECT employee, COALESCE(value, 0)
FROM mytable
LEFT OUTER JOIN sales_2012
ON mytable.id = sales_2012.id
;
┌──────────┬────────┐
│ employee │ value │
├──────────┼────────┤
│ Jim │ 40 │
│ Rob │ 0 │
└──────────┴────────┘
答案 1 :(得分:0)
关键元素是使用 setUseOpenCL(true)
而不是隐含LEFT JOIN LATERAL
的隐式CROSS JOIN LATERAL
,其中只有逗号的短符号被解释。< / p>
What is the difference between LATERAL and a subquery in PostgreSQL?
Call a set-returning function with an array argument multiple times
查询可以简单地为:
SELECT t.id, t.employee, s.*
FROM mytable t
LEFT JOIN LATERAL jsonb_to_recordset(t.data->'sales')
AS s(yr int, value int) ON s.yr = 2012;
我们可以通过yr = 2012
方便地选择销售,而不会让员工失去结果。
用“无数据”来美化。 value
列必须是匹配的字符串类型:
SELECT t.id, t.employee
, COALESCE(s.yr, 2012) AS yr
, COALESCE(s.value, 'No Data') AS value
FROM mytable t
LEFT JOIN LATERAL jsonb_to_recordset(t.data->'sales')
AS s(yr int, value text) ON s.yr = 2012;
以这些缺失(可能)的细节为基础:
empoyee
为UNIQUE NOT NULL
。每个员工在data
- data
的销售额可以是0年,可以为NULL。
yr
和value
存储有效的整数。其他适应类型。
正确的表格定义:
CREATE TABLE mytable (
id serial PRIMARY KEY
, employee text UNIQUE NOT NULL
, data jsonb
);
LATERAL JOIN
?根据评论中的要求,这些链接应该有所帮助,尤其是初学者的第一个: