0

我有这个查询,工作得很好:

 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;

让我解释一下情况。

表格:

  • personID 作为列。
    • field代表一列的表,例如name, varchar(类似的东西)
    • person_field代表那个人和那个字段的价值。像这样:
    • unit与这个问题无关

例如。:

  Person id 1
  Field  id 1 {name, eg)
  value "Marco Noronha"

所以函数“comparestrings”返回一个从 0 到 1 的双精度数,其中 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
4

2 回答 2

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标记为stableor immutable,它就会足够快):

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;
于 2013-02-25T16:05:35.537 回答
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.

于 2013-02-25T15:14:01.170 回答