2013-02-25 45 views
0

我有这个疑问,伟大的工作:复杂的查询复制结果(同一ID,不同列中的值)

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" 

所以函数“比较字符串”返回从0到1的双精度值,其中1是精确的('Marco'=='Marco')。

所以,我需要所有人的相似度在0.35以上,我也需要它的相似性。

没问题,查询工作正常,因为它suppost。但现在我有一个新的要求,即表“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 

并让supose,我想带来的价值是1,0.751121(女巫是DATE整合了最新值)

我觉得我应该这样做order by date desc limit 1 ...

但是,如果我做这样的事情,查询将返回只有一个人=/

像:

1, 0.751121 

当我真的想:

1, 0.751121 
2, 0.51212 
3, 0.42454 
+0

我做了,已经。有什么你不明白的吗? – 2013-02-25 15:46:35

回答

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:你所提到的ALTER日期(我们为了递减,所以我们每个p.id得到最旧的)

顺便说一句,好像你不都需要一个子查询(只是确保comparestrings被标记为stableimmutable,并且这将是速度不够快):

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; 
+0

Matheus,我不能在数据库执行两次compareString函数,因为我在“person_field”表上有=〜22kk行。 :( – 2013-02-25 16:24:10

+0

行动,没有正确地读你的答案。谢谢你,你救了我的一天! – 2013-02-25 16:47:14

+0

@ d34d_d3v1l,我很高兴我可以帮助... = D – MatheusOl 2013-02-25 17:09:48

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

+0

哇,我没听懂。你为什么选择UNIT?我需要选择person_id和相似度。单位只是一个where子句,因为这个人有一个属性'id_unit',我需要按单位过滤它。你能再帮助我吗?谢谢! – 2013-02-25 15:45:59

+0

@ d34d_d3v1l。 。 。我只是在显示你要替换代码的位置。 – 2013-02-25 15:59:46