【问题标题】:Retrieve multiple rows with query using AND and OR使用 AND 和 OR 通过查询检索多行
【发布时间】:2015-03-18 18:04:21
【问题描述】:

我想使用相同的 id 检索多行。因此,有了这个表“component_property”,我想根据我的 SQL 查询(在下面检查)得到 2 条记录,id:8 和 9,但当然也没有检索到,因为我正在检查 cp.property_id = 9102 及更高版本并检查 cp.property_id = 8801 是否同时是不可能的。

ID;type_id;name;desc;property_id,value
--------------------------------------
8;3832;"amplifier1";"";8801;"3"
8;3832;"amplifier1";"";9102;"4015"
9;3832;"amplifier2";"";8801;"3"
9;3832;"amplifier2";"";9102;"4016"

这是我此刻的查询,它什么也没得到。

SELECT c.id, c.type_id, cp.property_id, cp.value 
FROM components_component AS c 
INNER JOIN components_componentproperty AS cp 
ON c.id = cp.component_id 
WHERE 
(cp.property_id = 9102  AND cp.value IN ('4015', '4016')) 
OR
(cp.property_id = 8801  AND cp.value = '3') 
AND c.type_id = 3832

组件 ===> 组件属性

组件

id serial NOT NULL,
type_id integer NOT NULL,
name character varying(50) NOT NULL,
description character varying(255),

组件属性

id serial NOT NULL,
component_id integer NOT NULL,
property_id integer NOT NULL,
value character varying(255),

属性

id serial NOT NULL,
code character varying(10),
preferred_name character varying(50),

我的预期结果是:

id;name
-------
8;amplifier1
9;amplifier2

【问题讨论】:

  • 显示你的预期输出
  • 还显示从components_component 提取的结构/示例数据 - 我还看到你有c.type_id = 3832 也许你的意思是cp.type_id ...
  • @unique_id 嗯,我得到 4 条记录,我应该只得到 2 条记录,它们代表与属性值匹配的 2 个组件。

标签: sql postgresql postgresql-9.1 relational-division


【解决方案1】:

这是一个关系划分的例子:

SELECT c.id, c.name
FROM   components_componentproperty cp1
JOIN   components_componentproperty cp2 USING (component_id)
JOIN   components_component         c   ON c.id = cp1.component_id
WHERE  cp1.property_id = 9102  AND cp1.value IN ('4015', '4016')
AND    cp2.property_id = 8801  AND cp2.value = '3'
AND    c.type_id = 3832
GROUP  BY c.id;

我们在这里汇集了一系列相关技术:

检查大量属性

您可以扩展上面的查询,并且对于一个充满属性的手,这将是最快的解决方案之一。对于更大的数字,走这条路会更方便(也开始更快):

5 个属性的示例,根据需要展开:

SELECT c.id, c.name
FROM  (
   SELECT id
   FROM  (
      SELECT component_id AS id, property_id  -- alias id just to shorten syntax
      FROM   components_componentproperty
      WHERE  property_id IN (9102, 8801, 1234, 5678, 9876)  -- expand as needed
      GROUP  BY 1,2
      ) cp1
   GROUP  BY 1
   HAVING count(*) = 5  -- match IN expression
   ) cp2
JOIN   components_component c USING (id);

内部子查询cp1 的额外步骤只是必要的,因为您显然在components_componentproperty 中每个(component_id, property_id) 有多个条目。我们可以cp1cp2合二为一并检查

HAVING count(DISTINCT property_id) = 5

但我预计这会更昂贵,因为count(DISTINCT col) 需要每行一个排序操作。

对于很长的列表,IN 是一个糟糕的选择。考虑:

【讨论】:

  • 如果有更多的属性要比较怎么办。属性是动态的,所以我可以比较 2,3 或 10。
  • @Ruben:我为此添加了一个解决方案。
  • 它完成了这项工作:SELECT c.id, c.name FROM components_component AS C WHERE c.id IN (SELECT component_id FROM components_componentproperty WHERE property_id = 9102 AND value IN ('4015', '4016' )) AND c.id IN (SELECT component_id FROM components_componentproperty WHERE property_id = 8801 AND value IN ('3'))
  • @Ruben:是的,应该也可以。使用EXPLAIN ANALYZE 测试性能。连接通常比IN 快。对于许多重复匹配,EXISTS 通常更快。简而言之:IN 只对小套装有竞争力。
猜你喜欢
  • 2017-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-23
相关资源
最近更新 更多