我的数据如下:
ID Name Data 1 Joe ["Mary","Joe"] 2 Mary ["Sarah","Mary","Mary"] 3 Bill ["Bill","Joe"] 4 James ["James","James","James"]
我想编写一个查询,该查询从数组中选择LAST元素,这不等于Name字段。例如,我希望查询返回以下结果:
ID Name Last 1 Joe Mary 2 Mary Sarah 3 Bill Joe 4 James (NULL)
我正在接近-我可以使用以下查询选择最后一个元素:
SELECT ID, Name, (Data::json->(json_array_length(Data::json)-1))::text AS Last FROM table; ID Name Last 1 Joe Joe 2 Mary Mary 3 Bill Joe 4 James James
但是,我还需要一个级别-评估最后一个项目,如果它与名称字段相同,则尝试倒数第二个字段,依此类推。
任何帮助或指针将不胜感激!
json
在9.3版中很难做到这一点,因为缺少有用的功能。
嵌套LEFT JOIN LATERAL(干净且符合标准),将双引号从json铸造后修剪到text。请参阅下面的链接。
LEFT JOIN LATERAL
text
SELECT DISTINCT ON (1) t.id, t.name, d.last FROM tbl t LEFT JOIN LATERAL ( SELECT ('[' || d::text || ']')::json->>0 AS last FROM json_array_elements(t.data) d ) d ON d.last <> t.name ORDER BY 1, row_number() OVER () DESC;
尽管这可行,但我从未见过失败,但未嵌套元素的顺序取决于未记录的行为。见下面的链接!使用@pozs在注释中提供的表达式 改进了从json到的转换。仍然有点破旧,但应该是安全的。text
SELECT DISTINCT ON (1) id, name, NULLIF(last, name) AS last FROM ( SELECT t.id, t.name ,('[' || json_array_elements(t.data)::text || ']')::json->>0 AS last , row_number() OVER () AS rn FROM tbl t ) sub ORDER BY 1, (last = name), rn DESC;
SELECT
rn
(last = name)
ORDER BY
NULLIF
NULL
SQL提琴。
jsonb
第9.4页提供了所有必要的改进:
SELECT DISTINCT ON (1) t.id, t.name, d.last FROM tbl t LEFT JOIN LATERAL json_array_elements_text(data) WITH ORDINALITY d(last, rn) ON d.last <> t.name ORDER BY d.rn DESC;
使用jsonb_array_elements_text()了jsonb。其他都一样。
jsonb_array_elements_text()
手册中的json /jsonb函数