我试图编写一个SQL语句(在本例中为postgresql)来汇编名为" subfield "的表格中的值。这些都与特定的varfield_id有关。
来自子字段的大部分数据不会重复,但标记为" c"的数据除外。带有" c"标签的值的顺序然后由display_order定义,它是一个int。
我的目标是只选择具有最小值display_order的行的内容值,标记为" c" (并符合其他JOIN标准)。我在下面列出了我的SQL以及一个record_num的输出样本,特别是可以帮助清理的东西。
SELECT
r.record_num, a.content, q.content, c.display_order, c.content, d.content
FROM
db.subfield a
LEFT OUTER JOIN
db.subfield q
ON
a.varfield_id = q.varfield_id and q.tag = 'q'
LEFT OUTER JOIN
db.subfield c
ON
a.varfield_id = c.varfield_id and c.tag = 'c'
LEFT OUTER JOIN
db.subfield d
ON
a.varfield_id = d.varfield_id and d.tag = 'd'
JOIN
db.record_metadata r
ON
a.record_id = r.id and r.record_type_code = 'b'
WHERE
a.marc_tag = '100' and a.tag = 'a' and r.record_num = 2594119
--SAMPLE OF RETURNED DATA
--r.record_num; a.content; q.content; c.display_order; c.content; d.content;
--2594119; "Name"; "(other Name)"; 2; "Name Title 2"; "YEAR-YEAR";
--2594119; "Name"; "(other Name)"; 1; "Name Title 1"; "YEAR-YEAR";
是否有一种简单的方法可以只返回c.display_order最小的行?我想最终针对完整的子字段数据表运行此查询,并且不会限制特定的记录号。换句话说,我希望每个标签值只返回一行' a'在子字段中找到,包含具有非重复标记值的所有其他子字段值,' q'并且只有标签值' c'使用最小的display_order。
感谢愿意在这里帮忙的人!
答案 0 :(得分:0)
SELECT r.record_num, a.content, q.content
, c.display_order, c.content, d.content
FROM db.subfield a
LEFT OUTER JOIN db.subfield q
ON a.varfield_id = q.varfield_id AND q.tag = 'q'
LEFT OUTER JOIN db.subfield c
ON a.varfield_id = c.varfield_id AND c.tag = 'c'
AND NOT EXISTS (
SELECT * FROM db.subfield nx
WHERE nx.varfield_id = c.varfield_id -- <<-- same
AND nx.tag = c.tag -- <<-- same
AND nx.display_order < c.display_order -- <<--- different
)
LEFT OUTER JOIN db.subfield d
ON a.varfield_id = d.varfield_id and d.tag = 'd'
JOIN db.record_metadata r
ON a.record_id = r.id and r.record_type_code = 'b'
WHERE a.marc_tag = '100' and a.tag = 'a'
and r.record_num = 2594119
;
答案 1 :(得分:0)
如果您使用的是postgresql 9.3或更高版本,则可以使用LATERAL JOIN
。这与带有子查询的LEFT JOIN
非常相似,但您可以从子查询中访问外部查询中的列:
SELECT r.record_num, a.content, q.content, c.display_order, c.content, d.content
FROM db.subfield a
LEFT OUTER JOIN db.subfield AS q
ON a.varfield_id = q.varfield_id AND q.tag = 'q'
LEFT JOIN LATERAL
( SELECT c.display_order, c.content
FROM db.subfield AS c
WHERE a.varfield_id = c.varfield_id
AND c.tag = 'c'
ORDER BY c.display_order
) AS c ON TRUE
LEFT OUTER JOIN db.subfield AS d
ON a.varfield_id = d.varfield_id AND d.tag = 'd'
JOIN db.record_metadata AS r
ON a.record_id = r.id AMD r.record_type_code = 'b'
WHERE a.marc_tag = '100'
AND a.tag = 'a'
AND r.record_num = 2594119;
<强> Simplified example on SQL Fiddle 强>
您拥有的另一个选择是使用DISTINCT ON ()
:
SELECT r.record_num, a.content, q.content, c.display_order, c.content, d.content
FROM db.subfield a
LEFT OUTER JOIN db.subfield AS q
ON a.varfield_id = q.varfield_id AND q.tag = 'q'
LEFT OUTER JOIN
( SELECT DISTINCT ON (c.varfield_id), c.varfield_id c.display_order, c.content
FROM db.subfield AS c
WHERE c.tag = 'c'
ORDER BY c.varfield_id, c.display_order
) AS c
ON a.varfield_id = c.varfield_id
LEFT OUTER JOIN db.subfield AS d
ON a.varfield_id = d.varfield_id AND d.tag = 'd'
JOIN db.record_metadata AS r
ON a.record_id = r.id AMD r.record_type_code = 'b'
WHERE a.marc_tag = '100'
AND a.tag = 'a'
AND r.record_num = 2594119;