我有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_thing
是thing
的子代,任何事物都可以具有任意数量的子代(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
)是否为真(这只会得到所有三个条件各产生一个结果的结果)。
但是AND
和OR
都可以怎么做?
其他说明:数据库布局是固定的,我无法通过合理的方式进行更改。这是一个已经很糟糕的系统。另外,布局对于我们的应用程序来说非常有意义。 最重要的是,速度至关重要,因此我正在寻找一个尽可能优化的查询-我想避免为每个联合使用单独的子查询(当然,尽管这是一个解决方案)。
-
下面是我的实际查询,它甚至合并了另一个中间表(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