2017-04-06 50 views
2

我想我已經達到了我對MySQL查詢知識的高峯。我似乎無法產生,我懷疑是一個複雜的查詢。以下是我的設置背景,然後是問題。我有3張桌子。爲了簡潔起見,我只列出相關的列。Mysql查詢,更具體地說,與Laravel雄辯

customers 
- id 

customer_fields 
- id 
- name 

customer_datas 
- id 
- customer_id 
- customer_field_id 
- value 

該設置允許客戶端創建附加到客戶的任意數量的字段。 customer_datas保存客戶字段的值並鏈接到數據項。例如:

customer (1 record) 
- id: 1 

customer_fields (2 records) 
- id: 1 
- name: firstname 

- id: 2 
- name: lastname 

customer_datas (2 records) 
- id: 1 
- customer_id: 1 
- customer_field_id: 1 
- value: John 

- id: 2 
- customer_id: 1 
- customer_field_id: 2 
- value: Doe 

這是問題所在。我能夠爲每個客戶甚至是客戶列表提供數據。我無法做的是按列排序數據,在這種情況下,它必須是某種僞列。

下面是一個例子。我不能只運行ORDER BY名字,因爲我的客戶表中沒有該列。它都是動態的,所以firstname是客戶端設置的字段,位於customer_fields表中。我希望能夠通過客戶端設置的任何customer_field進行排序,但是我擔心我對mysql查詢的瞭解有限。我也不確定Laravel雄辯能夠做到這一點。如果不是,我可以走上原始路線。

我從來沒有做過任何事情,所以我願意接受我的設置全錯的可能性。任何幫助將不勝感激。即使只是把我指向正確的方向。

此外,道歉,如果這已被覆蓋的地方。我覺得這是一個相當具體的案例,我找不到任何有關它的信息。

回答

0

感謝所有誰張貼。我拿出正確的解決方案,部分原因是所有的輸入:

我做了客戶的模型範圍

public function scopeOrderByCustomField($q, $field, $direction) 
{ 

    $q->select('customers.*') 
     ->join('customer_datas as ca', 'ca.customer_id', '=', 'customers.id') 
     ->join('customer_fields as cf', 'cf.id', '=', 'ca.customer_field_id') 
     ->where('cf.name', $field) 
     ->groupBy('customers.id') 
     ->orderBy('ca.value', $direction); 

} 

我不得不添加的選擇,因爲在客戶表中的ID是被加入和groupBy覆蓋需要添加,以及將客戶分組到單個實體:)

+0

您不需要通過'customers.id'進行分組,因爲每個客戶只能有一個「firstname」。如果不是這樣,'ORDER BY ca.value'就沒有多大意義。另請注意,您無法使用數字值正確排序。 –

+0

我的例子很基礎。在我的實際工作流程中,我的字段具有多個值,如電話,傳真等......沒有羣組,我遇到了問題。在我的列表中,我只需要爲每個具有多個值的字段顯示主要值。 感謝您讓我意識到數值問題的排序。我想,一旦出現這個問題,我會處理它,嘿 – Patrick

0

我感覺你對你的困惑。有時候Eloquent並不是正確的查詢方式,因爲Eloquent會執行多個查詢來獲取數據。這可能會導致混淆如何正確構建您的查詢。

最終,99%的時間用於更大,更復雜的查詢,您將需要使用Fluent查詢生成器。

下面是使用Customer型號上的自定義local Query Scope的示例,該型號使用Fluent Query Builder

public function scopeOrderByCustomField($field, $direction) { 
    Customer::join('customer_datas as ca', 'ca.customer_id', '=', 'customer.id') 
     ->join('customer_fields as cf', 'cf.id', '=', 'ca.customer_field_id') 
     ->where(cf.name, $field) 
     ->orderBy('ca.value', $direction) 
} 

最終應給你Customer名單中$field排序您傳遞中去$direction你提供。

在實際應用中,它會是這個樣子:

$customers = Customer::orderByCustomField('first_name', 'ASC')->get(); 

注意,它調用->get()自己是重要的,因爲queryScope返回Query Builder的一個實例,因此沒有結果被取出,直到調用->get()->first()

+0

啊,我會試試這個,謝謝。該函數應該是scopeOrderByCustomField,但是,正確嗎? – Patrick

+0

@帕特里克Yup!更新了答案,對此很抱歉。 – Ohgodwhy

+0

不錯......我擔心這個問題仍然是一樣的。我的customer_fields表沒有列姓或名。所以我必須做orderBy('cf.name','asc'),但這不是我需要的:(我需要按姓氏排序,例如asc,所以我會得到John Doe,John Hancock,等等...雖然我不確定'orderBy()'是否在範圍內工作,但我沒有要訂購的列,因爲它是作爲customer_fields表中的一行動態創建的 – Patrick

0

你讓它過於複雜。所有這些數據都可以放到一張表中,客戶表中。

customers 
    - id 
    - firstname 
    - lastname 

那麼也許如果你喜歡地址表,打破了數據。

addresses 
- id 
- customer_id 
- street 
- city 
- zip 
- etc..... 

那麼你將建立客戶並基於CUSTOMER_ID他/她的地址,等等之間的關係......你可以閱讀更多關於laravel文檔的關係。 [laravel關係] [1]。 這對新表格有意義。

沒有理由將firstname的表格指向 帶有實際「firstname」的另一個表格。


UPDATE


好,然後讓另一臺

customer_data 
    - id 
    - customer_id 
    - field_name 
    - field_data 

您可以動態地添加和刪除儘可能多的領域,你會從該表像。儘管如此,保持簡單。

UPDATE

$data = DB::table('customer_datas') 
    ->where('field_name', 'first_name') 
    ->orderBy('field_data', 'desc') 
    ->get(); 
+0

整個問題是讓這些字段動態變化,這樣客戶端就可以添加和刪除列他們自己也允許刪除一個有附加數據的列,但仍然保留數據。也許我沒有正確解釋,我對此表示歉意。 – Patrick

+0

@Patrick不用擔心,我只是覺得你可以做你的試圖做的更容易,然後你的想法。檢查我的更新。 – cmac

+0

@帕特里克它基本上是你t以前只有一張桌子。沒有理由讓一個表中的字段名稱指向另一個包含數據的表。 – cmac