2012-11-01 56 views
0

與最大匹配的字符串行說我有這樣的:查找橫跨兩列

page_url      | canvas_url 
--------------------------------------------------------------- 
http://www.google.com/  | http://www.google.com/barfoobaz 
http://www.google.com/foo/bar | http://www.google.com/foo 

我想找到我的字符串的最長匹配下令開始行。我面臨的問題是找到最長的匹配字符串,而不是匹配的行也匹配。即

http://www.google.com/foo匹配行1 page_url和​​第2行,但如果它的兩列的長度,而不是匹配它會認爲第1行是更好的匹配爲​​行1更長。

我可以抓住所有的比賽,然後在代碼過濾長度做這樣的事情:

​​

或執行2個subselections抓的​​各page_url最匹配,然後篩選到1碼,但我寧願(除了任何荒謬的性能問題)擁有數據庫只是返回我需要的東西。

我的直接問題是MySQL,但我需要針對SQLite和Postgress,所以我很樂意回答這些問題。

對此提出建議?

+0

我不明白。爲什麼row1的page_url匹配「http:// www.google.com/hi」?第1行中的page_url在末尾沒有「hi」...您是否在嘗試查找與您的搜索字符串具有最多字符的網址?還是別的?也許你可以擴展你的例子,更清楚地顯示哪些字符串匹配什麼網址,然後是什麼使一個網址優先於另一個網址? – MatBailie

+0

@Dems啊有人發現,我以爲自己陷入了一個角落。我會解決這個問題。 –

+0

@Dems更新更好的例子,抱歉。 –

回答

3

這將努力獲得最長的實際匹配長度(不只是在記錄最長的網址):

-- Get page_url matches 
SELECT *, LENGTH(page_url) AS MatchLen 
FROM app 
WHERE 'http://www.google.com/foo' LIKE CONCAT(page_url, '%') -- can't tell from question if this should be reversed 
UNION ALL 
-- Get canvas_url matches 
SELECT *, LENGTH(canvas_url) AS MatchLen 
FROM app 
WHERE 'http://www.google.com/foo' LIKE CONCAT(canvas_url, '%') 
-- Bring the longest matches to the top 
ORDER BY MatchLen DESC -- May need to add a tie-breaker here 
LIMIT 1 

這裏是一個running example on SqlFiddle

+0

CONCAT必須放在列上,因爲我想知道列值是否是我的字符串的開始,而不是字符串是列值的開始。聯盟的想法是相當麻煩的。 –

+0

@KitSunde,然後我不明白canvas_url是如何匹配的。 –

+0

嗯,它是第二排匹配'page_url'。我換了例子中的值。 –

0

如果您需要查找第一行,您需要訂購和限制。你必須是一個聰明一點關於如何安排呢:

SELECT *, LENGTH(canvas_url), LENGTH(page_url) 
FROM app 
WHERE canvas_url like concat('http://www.google.com/foo' '%') OR 
     page_url like concat('http://www.google.com/foo', '%') 
order by (case when canvas_url like concat('http://www.google.com/foo' '%') and 
        page_url like concat('http://www.google.com/foo', '%') and 
        LENGTH(canvas_url) < LENGTH(page_url) 
       then LENGTH(page_url) 
       when canvas_url like concat('http://www.google.com/foo' '%') and 
        page_url like concat('http://www.google.com/foo', '%') and 
        LENGTH(canvas_url) >= LENGTH(page_url) 
       when canvas_url like concat('http://www.google.com/foo' '%') 
       then LENGTH(canvas_url) 
       else LENGTH(page_url) 
      end) 
limit 1 

這是通過匹配字符串的較長訂貨,然後返回一行。請注意,LIMIT不是標準的,所以不同的數據庫有不同的返回一行的機制。

+0

按照最長的網址排序,而不是最長的匹配網址。另外,'LIKE'謂詞似乎與我相反。 –

+0

即使存在,我也不知道這種情況,所以非常酷。 LIMIT'應該在我所針對的所有3個數據庫中工作。然而'CONCAT'不適用於支持ANSI SQL的數據庫(Postgress,SQLite)我使用'||',而MySQL不支持'||'而不啓用ansi支持。 –

+0

按照GREATEST(LENGTH(page_url),LENGTH(canvas_url))排序? – fthiella

1

也許你只是需要這樣的東西?

SELECT page_url as url, LENGTH(page_url) as len 
FROM pages WHERE 'http://www.google.com/foo' LIKE CONCAT(page_url, '%') 
UNION 
SELECT canvas_url as url, LENGTH(canvas_url) as len 
FROM pages WHERE 'http://www.google.com/foo' LIKE CONCAT(canvas_url, '%') 
ORDER BY len DESC 
LIMIT 1 
+0

order by len _desc_? –

+0

感謝您的評論...順序desc ...不完全,不清楚如何計算最長的比賽,但我想我現在有一個想法,我會編輯我的答案 – fthiella

+0

是的,我是被問題和給出的例子匹配所困惑。也就是說,在'order by'中也可能需要打破平局。 –