我有这个问题,工作得很好:
SELECT * FROM
(
select
p.id,
comparestrings('marco', pc.value) as similarity
from
unit u, person p
inner join person_field pc ON (p.id = pc.id_person)
inner join field c ON (pc.id_field = c.id AND c.flag_name = true)
where ( u.id = 1 ) AND p.id_unit = u.id
) as subQuery
where
similarity is not null
AND
similarity > 0.35
order by
similarity desc;
让我解释一下情况。
TABLES:
person
ID为列。
field
表示列的表,例如name, varchar
(类似的内容)person_field
表示该人和该字段的值。就像这样:unit
与此问题无关例如:
Person id 1
Field id 1 {name, eg)
value "Marco Noronha"
因此“comparetrings”函数返回一个从0到1的double,其中1是精确的('Marco'=='Marco')。
所以,我需要所有相似度都超过0.35的人,我也需要它的相似性。
没问题,查询工作正常,因为它是支持。但是现在我有了一个新的要求,表“person_field”将包含一个更改日期,以跟踪这些行的变化。
例如:
Person ID 1
Field ID 1
Value "Marco Noronha"
Date - 01/25/2013
Person ID 1
Field ID 1
Value "Marco Tulio Jacovine Noronha"
Date - 02/01/2013
所以我需要做的是,只考虑最新的行!! 如果我执行相同的查询,结果将是(例如):
1, 0.8
1, 0.751121
2, 0.51212
3, 0.42454
//other results here, other 'person's
并且让我想要带来的值是1,0.751121(女性是DATE的最低值)
我想我应该做order by date desc limit 1
...
但如果我这样做,查询将只返回一个人= /
像:
1, 0.751121
当我真正想要的时候:
1, 0.751121
2, 0.51212
3, 0.42454
答案 0 :(得分:1)
您可以在子查询中使用DISTINCT ON(p.id)
:
SELECT * FROM
(
select
DISTINCT ON(p.id)
p.id,
comparestrings('marco', pc.value) as similarity
from
unit u, person p
inner join person_field pc ON (p.id = pc.id_person)
inner join field c ON (pc.id_field = c.id AND c.flag_name = true)
where ( u.id = 1 ) AND p.id_unit = u.id
ORDER BY p.id, pc.alt_date DESC
) as subQuery
where
similarity is not null
AND
similarity > 0.35
order by
similarity desc;
请注意,要使其正常工作,我需要添加ORDER BY p.id, pc.alt_date DESC
:
p.id
:DISTINCT ON
要求(如果您使用ORDER BY
,则第一个字段必须与DISTINCT ON
完全相同); pc.alt_date DESC
:您提到的更改日期(我们订购了desc,因此我们按每个p.id
获取最旧的日期)顺便说一句,您似乎根本不需要子查询(只需确保comparestrings
被标记为stable
或immutable
,并且&#39 ;会足够快):
SELECT
DISTINCT ON(p.id)
p.id,
comparestrings('marco', pc.value) as similarity
FROM
unit u, person p
inner join person_field pc ON (p.id = pc.id_person)
inner join field c ON (pc.id_field = c.id AND c.flag_name = true)
WHERE ( u.id = 1 ) AND p.id_unit = u.id
AND COALESCE(comparestrings('marco', pc.value), 0.0) > 0.35
ORDER BY p.id, pc.alt_date DESC, similarity DESC;
答案 1 :(得分:0)
将对person
的引用更改为子查询,如以下示例所示(子查询是名为p
的子查询):
. . .
from unit u cross join
(select p.*
from (select p.*,
row_number() over (partition by person_id order by alterationdate desc) as seqnum
from person p
) p
where seqnum = 1
) p
. . .
这使用row_number()
函数来标识最后一行。我使用了一个额外的子查询来将结果限制为最新的。您也可以将其包含在on
子句或where
子句中。
我还将,
更改为明确的cross join
。