2012-02-11 54 views
2

我正在嘗試爲我的應用程序創建一個查找腳本。當前的表結構如下所示:如何將分組的行數據轉換爲查找列?

id  userid  profile_field  profile_value 
----------------------------------------------------- 
1  1   firstname   John 
2  1   lastname   Smith 
3  1   address    123 anywhere 
4  1   city    city 
5  2   firstname   Jane 
6  2   lastname   Smith 
7  2   address    456 anywhere 
8  2   city    town 

我正在嘗試編寫一個查詢,該查詢將允許我根據用戶輸入搜索用戶。

例如,我的管理員希望搜索姓名爲「smith」的用戶。在這個例子中,它會返回用戶標識1和2.

這是可能的與MySQL?到目前爲止,我已經研究了mysql的group_concat函數,但它似乎將所有內容放入字符串而不是列。因此,我無法生成適當的where子句進行搜索。

編輯:我必須道歉,我應該更清楚。

我還需要考慮有多個輸入。例如,搜索名字如「john」和姓氏如「smith」的用戶。在這個例子中,它只會返回用戶標識1.

這是我遇到麻煩的部分。再次抱歉!

+0

閱讀有關在MySQL樞轉。 – 2012-02-11 14:26:14

+0

您的設計未規範化。你永遠不會得到最佳的解決方案。 – 2012-02-11 14:35:29

+0

你真的需要一個嚴肅的理由來建立一個像這樣的表結構,而不是像列表名,姓氏等那樣爲每個用戶設置一行。實體屬性值模型往往存在很多性能問題。 – piotrm 2012-02-11 14:38:05

回答

0
SELECT 
    `userid` 
FROM 
    `table` 
WHERE 
    `profile_field` = 'lastname' 
     AND 
    `profile_value LIKE %smith%; 
0

剛剛嘗試這樣的事:

SELECT userid FROM table WHERE profile_value='Smith' 
3

試試這個:

SELECT group_concat(DISTINCT UserID) as Results 
FROM tableName 
WHERE profile_value like CONCAT('%', 'Smith' ,'%') 

這將返回

Results 
========== 
1, 2 

OR

SELECT UserID as Results 
FROM tableName 
WHERE profile_value like CONCAT('%', 'Smith' ,'%') 

這將返回

Results 
========== 
1 
2 
+0

除非我誤解了這個問題,這個答案對我來說似乎是對的 – 2012-02-11 15:02:47

1

可能不是最好的解決方案,但我們決定去與一個cron作業,這將創建一個聚合表。然後,我們可以使用聚合表執行查找。

create table profile_values_aggregate 
    select users.uid,  
     (SELECT value FROM profile_values WHERE fid=1 and profile_values.uid=users.uid) AS cust_fname, 
     (SELECT value FROM profile_values WHERE fid=2 and profile_values.uid=users.uid) AS cust_lname 
     ... ... ... 
    FROM profile_values 
    inner join users on users.uid=profile_values.uid 
    GROUP BY uid 

查詢想法是從這裏取:https://stackoverflow.com/a/7976379/1203831

+0

I我已經添加了一個答案,因爲我認爲這個解決方案會殺死你的服務器,因爲有這麼多的選擇 – 2012-02-12 20:58:22

0

感謝您向我們提供「不是最好的解決方案。」基於它,我想我明白你在做什麼。標準的做法是加入表本身這樣的:

SELECT pv1.`userid` FROM `profile_value` AS pvfirst 
JOIN `profile_value` AS pvlast ON pvfirst.`userid` = pvlast.`userid` 
WHERE 
pvfirst.`profile_field` = 'firstname' 
AND 
pvfirst.`profile_value` LIKE '%john%' 
AND 
pvlast.`profile_field` = 'lastname' 
AND 
pvlast.`profile_value` LIKE '%smith%' 
; 

我希望這有助於。如果你有任何後續問題,請不要猶豫。

+0

因此,如果我需要做多達15個可能的搜索(名字,姓氏,城市,州,郵編,國家,等等),我需要做15個連接? 我現在沒有測試,但這樣的查詢性能如何? – jellysandwich 2012-02-13 13:50:10

+0

1.你提高性能是一件好事,因爲這個表結構是一個完美的候選者,需要四列中的每一列都有一個索引。無論您是否有每列索引,都會產生巨大的性能差異n他們在WHERE子句中。 2. MySQL知道如何優化查詢,以便在添加所有WHERE條件時,連接並不像您擔心的那樣糟糕。您可以直觀地驗證這一點,通過意識到您基本上只連接來自每個15個表的一行,或者換句話說,連接每行15個表。試試看看。 – 2012-02-14 05:48:57

0

這是怎麼回事?

select userid from profile_values 
where 
    (profile_field = 'firstname' and profile_value = 'John') or 
    (profile_field = 'lastname' and profile_value = 'Smith') 
group by userid 
having count(*) = 2 

數字2是由OR分隔的條件數量。

編輯:

這似乎爲工作「或」正常的,但如果我一直在尋找一些與第一名稱「John」和最後一個名字也沒有的情況下工作「史密斯」... - jellysandwich

它工作的也很好。正如我告訴你之前,如果該數目是2的條件對(每對是場 - 值比較)的量,然後與一個條件應該只有一個1 Example

select userid from profile_values 
where 
    (profile_field = 'firstname' and profile_value = 'John') 
group by userid 
having count(*) = 1 
+0

這似乎適用於「或」,但它不起作用的情況下,如果我正在尋找一些與第一個名字「約翰」和姓氏「史密斯」... – jellysandwich 2012-02-13 13:51:18

+0

添加更多詳細信息 – 2012-02-13 17:46:06