如何在PostgreSQL中有条件地提取特定字段

时间:2012-05-22 17:08:35

标签: database postgresql select conditional

不完全确定如何表达这一点,但希望有人可以提供帮助。这是我的问题。

我有一张表T,其中包含以下字段

ID      CF    Value
------------------------
976     13    Severity 1
978     36    branch a  
978     13    severity 1

我想提取属性分支为a且严重性为1的项目。

问题是,值字段用于分支和严重性,仅由13或36的不同CF值区分。如果项目同时具有两个属性,则会给出重复条目(例如,上面的ID 978)

所以我不能从D中选择value = branch a AND value = severity1。

我想要做的是选择 - 作为 - 来自以下字段

ID   Branch   Severity

如果cf = 36,则将值字段拉入Branch,如果cf = 13,则将值拉入Severity。

但是我不确定我是怎么做这个语法的。我已经尝试过一些Case和If语句,但一直都会出错。

任何帮助都非常感激。

感谢。

3 个答案:

答案 0 :(得分:1)

在必须应对这种模型时进行转向的标准方法是:

select id, 
       max(branch) as branch,
       max(severity) as severity
from (
    select id, 
           case 
             when cf = 36 then value
             else null
           end as branch,
           case 
             when cf = 13 then value
             else null
           end as severity
    from t
) p
group by id

这种“设计”被称为“实体 - 属性 - 价值”模式,而且 - 正如Catcall已经说过的那样 - 被认为是一种反模式。准确地说是检索事物的复杂方法。

如果您在互联网上搜索该术语,您将获得大量的点击率。

在PostgreSQL中,您还可以使用tablefunc模块中的交叉表函数,该函数实际上是在函数内动态创建上述语句。

http://www.postgresql.org/docs/current/static/tablefunc.html

使用交叉表函数,查询将如下所示:

SELECT *
FROM crosstab(
  'select id, cf, value
   from t
   where cf in (13,36)
   order by 1,2'::text)
AS ct(id integer, severity text, branch text);

答案 1 :(得分:0)

您可以通过这种方式获取身份证号码。

select id
from your_table
where value = 'branch a'
   or value = 'Severity 1'
group by id
having count(id) = 2

但总的来说,你会发现任何更复杂的东西都会让你陷入困境。这种结构是一种众所周知的反模式,这不是偶然的。

答案 2 :(得分:0)

您可以使用此类架构执行简单操作:

select id from t where cf = 36 and value = 'branch a'
intersect
select id from t where cf = 13 and value = 'severity1'

正如Catcall已经指出的那样,这个系统在一段时间后会变得相当笨拙。如果T中的id值引用某个实体表E,那么你可以创建一个像这样的视图:

create view e_attrs as
select e.id, t_36.value as branch, t_13.value as severity
from e
     left join t t_36 on t_36.id = e.id and t_36.cf = 36
     left join t t_13 on t_13.id = e.id and t_13.cf = 36

然后希望加入淘汰(来自postgresql 9.1,我认为)如果您在视图上查询,将删除针对T的无关连接。