复杂查询复制结果(相同的ID,不同的列值)

时间:2013-02-25 15:09:45

标签: sql postgresql

我有这个问题,工作得很好:

 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

2 个答案:

答案 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.idDISTINCT ON要求(如果您使用ORDER BY,则第一个字段必须与DISTINCT ON完全相同);
  • pc.alt_date DESC:您提到的更改日期(我们订购了desc,因此我们按每个p.id获取最旧的日期)

顺便说一句,您似乎根本不需要子查询(只需确保comparestrings被标记为stableimmutable,并且&#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