不完全确定如何表达这一点,但希望有人可以提供帮助。这是我的问题。
我有一张表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语句,但一直都会出错。
任何帮助都非常感激。
感谢。
答案 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的无关连接。