2013-02-25 22 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