Sql 使用多个侧向联接构建动态查询

Sql 使用多个侧向联接构建动态查询,sql,postgresql,entity-attribute-value,Sql,Postgresql,Entity Attribute Value,我正在根据用户指定字段上的用户提交条件构建动态查询 我有两张桌子 Visitors(id, name, email...) 和 Trackings(id, visitor_id, field, string_value, integer_value, boolean_value, date_value) 这些条件以前面构建的SQL片段数组的形式出现。在访问者表中硬编码的属性的默认筛选器,以及用户提交并存储在EAV架构(跟踪)中的值的自定义筛选器 例如: Default: {"name ILI

我正在根据用户指定字段上的用户提交条件构建动态查询

我有两张桌子

Visitors(id, name, email...)

Trackings(id, visitor_id, field, string_value, integer_value, boolean_value, date_value)
这些条件以前面构建的SQL片段数组的形式出现。在
访问者表中硬编码的属性的默认筛选器,以及用户提交并存储在EAV架构(跟踪)中的值的自定义筛选器

例如:

Default:
{"name ILIKE 'Jack'", "(last_seen < (current_date - (7 || ' days')::interval))"}

Custom:
{"field = 'number_of_orders' > 10", "is_pro_user = true"}
这非常有效,但恐怕没有办法表达自定义属性的
unknown
过滤器。因为它需要使用一个
左外部联接
,或者一个
不存在
子查询来访问外部作用域

我现在正在寻找其他方法来实现上述功能,但也支持这种查询。我的想法如下,对每个条件使用一系列横向连接,但这似乎不会在超过1-2个条件/连接时表现得很好

select v.id, v.name from visitors v
inner join lateral ( <-- custom fields
    select * from trackings t
    where field = 'admin'
) as t1 on t1.visitor_id = v.id
inner join lateral (
    select * from trackings t
    where field = 'users_created' 
) as t2 on t2.visitor_id = v.id
inner join lateral (
    select * from trackings t
    where field = 'teams_created' and integer_value > 0
) as t3 on t3.visitor_id = v.id
where v.app_id = 'ASnYW1-RgCl0I' and (v.type = 'lead' or v.type = 'user')
and name ILIKE 'mads' and email is not null // <-- default fields
从访问者v中选择v.id、v.name
内连接横向(0
)与t3上的t3相同。访客id=v.id
其中v.app_id='ASnYW1-RgCl0I'和(v.type='lead'或v.type='user')

我的名字像“mads”,email不是空的//我认为这里没有任何横向连接的必要。您没有在派生表中使用外部表中的列。一个好的旧(左)连接就可以了。我明白了,但是我仍然会在同一个表上执行很多连接欢迎来到“EAV”反模式的危险是的,但是我仍然设法使用第一个选项表达了几乎所有我想要的东西。这只是因为除了像
大于
包含
,这样的过滤器之外,我还需要
值未知的
过滤器,我希望这将是一个接近我最初提出的解决方案。我不认为这里需要横向连接。您没有在派生表中使用外部表中的列。一个好的旧(左)连接就可以了。我明白了,但是我仍然会在同一个表上执行很多连接欢迎来到“EAV”反模式的危险是的,但是我仍然设法使用第一个选项表达了几乎所有我想要的东西。这只是因为除了像
大于
包含
,这样的过滤器之外,我还需要
值未知的
过滤器,我希望这将是一个接近我最初提出的解决方案。
select v.id, v.name from visitors v
inner join lateral ( <-- custom fields
    select * from trackings t
    where field = 'admin'
) as t1 on t1.visitor_id = v.id
inner join lateral (
    select * from trackings t
    where field = 'users_created' 
) as t2 on t2.visitor_id = v.id
inner join lateral (
    select * from trackings t
    where field = 'teams_created' and integer_value > 0
) as t3 on t3.visitor_id = v.id
where v.app_id = 'ASnYW1-RgCl0I' and (v.type = 'lead' or v.type = 'user')
and name ILIKE 'mads' and email is not null // <-- default fields