如何添加不符合条件的行?

时间:2015-07-09 21:32:30

标签: sql postgresql postgresql-9.4 jsonb

我知道我可能只是在考虑这个错误。我有以下结构:

  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作为合并的第二个参数,因为我收到错误"类型双精度的输入语法无效:'没有数据'"

2 个答案:

答案 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>

查询可以简单地为:

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;

以这些缺失(可能)的细节为基础:

  • 表格中每位员工只有一行:empoyeeUNIQUE NOT NULL
  • 每个员工在data - data的销售额可以是0年,可以为NULL。

  • yrvalue存储有效的整数。其他适应类型。

正确的表格定义:

CREATE TABLE mytable (
  id       serial PRIMARY KEY
, employee text UNIQUE NOT NULL
, data     jsonb
);

什么是LATERAL JOIN

根据评论中的要求,这些链接应该有所帮助,尤其是初学者的第一个: