按n:m关系中的析取和合取进行过滤

时间:2018-11-23 11:05:45

标签: sql postgresql

我有4个这样的表(简化为相关列):

thing: id::numeric, some_info::text

mapping: thing_id::numeric, common_property_id::numeric

common_properties: id::numeric, some_info::text

children_of_thing id::numeric, thing_id::numeric, other_stuff::text

common_properties是可以附加到thing的属性,可以将任意数量的属性附加到任意数量的事物(n:m)。 children_of_thingthing的子代,任何事物都可以具有任意数量的子代(1:n)。

现在,我要计算应用了特定属性的所有子项。我的查询如下:

SELECT COUNT(DISTINCT children_of_thing.id) as count
     , thing.id as thing_id
FROM children_of_thing
    INNER JOIN thing ON children_of_thing.thing_id = thing.id
    LEFT JOIN (mapping
       INNER JOIN common_properties ON mapping.common_property_id = common_properties.id
    ) ON thing.id = mapping.thing_id
GROUP BY thing.id
WHERE ...

现在我的问题是:我怎样才能只选择具有的东西(前面的伪代码显然不能那样工作)

common_property.some_info = 'foo' AND (
    common_property.some_info = 'bar' OR
    common_property.some_info = 'baz'
)

我知道我可以按原样查询内部('bar' OR 'baz')-选择的DISTINCT可以确保即使两个条目相同,我也只计算一次当两个条件都成立时,将返回子代。

我还可以通过查询(foo ANDbar AND baz)并添加foo OR bar OR baz来查询所有属性(HAVING COUNT(DISTINCT common_property.id) = 3)是否为真(这只会得到所有三个条件各产生一个结果的结果)。

但是ANDOR都可以怎么做?

其他说明:数据库布局是固定的,我无法通过合理的方式进行更改。这是一个已经很糟糕的系统。另外,布局对于我们的应用程序来说非常有意义。 最重要的是,速度至关重要,因此我正在寻找一个尽可能优化的查询-我想避免为每个联合使用单独的子查询(当然,尽管这是一个解决方案)。

-

下面是我的实际查询,它甚至合并了另一个中间表(thing_variants-每个thing属于thing_variants中的变体之一,1:n)并在子级上进行过滤。我本来就把所有问题都排除在外,因为它使一切变得复杂,但是如果它有助于了解整个情况,那么我就不必隐藏它。

SELECT COUNT (DISTINCT children.id) as children_count
     , things.id as things_id,
     , things.meta_info as thing_info
     , thing_variants.id as thing_variant_id
     , thing_variants.meta_info as thing_variant_info
FROM children
     INNER JOIN things ON children.thing_id = things.id
     INNER JOIN thing_variants ON things.thing_variant_id = thing_variant.id
     LEFT JOIN (mapping
        INNER JOIN properties ON mapping.property_id = properties.id
     ) ON thing_variant.id = mapping.thing_variant_id
WHERE (children.something IS FALSE)
  AND (children.another_thing IS TRUE)
  AND (children.foobarbaz IS NULL)
GROUP BY things.id

0 个答案:

没有答案