使用依赖于另一个元素的元素进行查询

时间:2018-10-23 09:43:45

标签: sql postgresql

有一个Postgres数据库,该表有三列。数据结构在外部系统中,所以我无法对其进行修改。

每个对象都由三行表示(由列element_id标识-该列中具有相同值的行表示同一对象),例如:

key     value            element_id
-----------------------------------
status  active           1
name    exampleNameAAA   1
city    exampleCityAAA   1
status  inactive         2
name    exampleNameBBB   2
city    exampleCityBBB   2
status  inactive         3
name    exampleNameCCC   3
city    exampleCityCCC   3

在查询中,我想放置一些名称的列表,检查同一对象中带有keystatus的行的值是否为'active'并返回此对象的名称仅当状态为“有效”时。

因此,在此示例中,数据库表中包含三个对象。我想在查询中输入两个“名称”:

a)exampleNameAAA

b)exampleNameCCC

,结果应为: exampleNameAAA(因为我要了两个对象,而其中只有一个在active行中具有status值。

3 个答案:

答案 0 :(得分:0)

一个选项使用聚合:

SELECT
    MAX(CASE WHEN "key" = 'name' THEN "value" END) AS name
FROM yourTable
GROUP BY element_id
HAVING
    MAX(CASE WHEN "key" = 'name' THEN "value" END) IN
        ('exampleNameAAA', 'exampleNameCCC') AND
    SUM(CASE WHEN "key" = 'status' AND "value" = 'active' THEN 1 ELSE 0 END) > 0;

name
exampleNameAAA

Demo

这是关键方法,其中我们为每个element_id组隔离了单独的键和值。

答案 1 :(得分:0)

您可以使用EXISTS查询:

select e1.*
from element e1
where (e1.key, e1.value)  in ( ('name', 'exampleNameAAA'), ('name', 'exampleNameCCC'))
and exists (select *
            from element e2
            where e2.element_id = e1.element_Id  
              and (e2.key, e2.value) = ('status', 'active'));

在线示例:https://rextester.com/JOWED21150

答案 2 :(得分:0)

我喜欢这样表达:

SELECT MAX(t.value) FILTER (WHERE t.key = 'name') AS name
FROM t
GROUP BY t.element_id
HAVING MAX(t.value) FILTER (WHERE t.key = 'name') IN ('exampleNameAAA', 'exampleNameCCC') AND
       MAX(t.value) FILTER (WHERE t.key = 'status') = 'active';

总而言之,在这种情况下,exists解决方案的性能可能更高。聚合方法的优点在于,您可以轻松地将其他列(例如城市)引入select中。

SELECT MAX(t.value) FILTER (WHERE t.key = 'name') AS name,
       MAX(t.value) FILTER (WHERE t.key = 'city') as city

(注意:key是列的坏名称,因为它是SQL关键字。)