2010-03-12 74 views
1

我有人員,公司,員工,事件和事件種類。我正在製作一份報告/跟進表,其中人員,公司和員工是行,列是事件種類。複雜的SQL查詢幫助彙總嵌套子查詢的值

事件類型是簡單的值,描述:「承諾捐贈」,「收到捐款」,「打電話」,「跟進」等。事件類型的排序:

CREATE TABLE event_kinds (
    id, 
    name, 
    position); 

活動舉行實際參考事件:

CREATE TABLE events (
    id, 
    person_id, 
    company_id, 
    referrer_id, 
    event_kind_id, 
    created_at); 

referrer_id是另一種參考的人。這是發送信息/提示的人,並且是一個可選字段,儘管我有時想過濾具有特定引用者的event_kind,而我不想處理其他類型的事件。

注意我沒有員工ID參考。該參考存在,但暗含。我有應用程序代碼來驗證person_id和company_id是否真的引用員工記錄。其他的表是非常基礎的:

CREATE TABLE people (
    id, name); 

CREATE TABLE companies (
    id, name); 

CREATE TABLE employees (
    id, person_id, company_id); 

我想達到以下報告:

 
         Referrer  Phoned  Promised Donated 
    Francois       Feb 16th Feb 20th Mar 1st 
    Apple (Steve Jobs) Steve Ballmer      Mar 3rd 
    IBM     Bill Gates  Mar 7th 

第一行是一個人的記錄,第二是員工,而第三個是公司。如果我要求引薦者Bill Gates處理Phoned事件種類,我只會看到第三行,而要求Steve和Phoned則不會返回行。

現在,我做3個查詢,一個爲公司,一個爲人,最後一個爲員工。我想要訂購事件種類列,但我在應用程序代碼中執行此操作,並在那裏正確顯示它。以下是我目前所在的地方:

SELECT companies.id, 
     companies.name, 
     (SELECT events.id FROM events WHERE events.referrer_id = 1470 AND events.company_id = companies.id AND events.person_id IS NULL AND events.event_kind_id = 9 ORDER BY created_at DESC LIMIT 1) event_kind_9, 
     (SELECT events.id FROM events WHERE events.company_id = companies.id AND events.person_id IS NULL AND events.event_kind_id = 10 ORDER BY created_at DESC LIMIT 1) event_kind_10, 
     (SELECT events.created_at FROM events WHERE events.referrer_id = 1470 AND events.company_id = companies.id AND events.person_id IS NULL AND events.event_kind_id = 9 ORDER BY created_at DESC LIMIT 1) event_kind_9_order 
FROM "companies" 

SELECT people.id, 
     people.name, 
     (SELECT events.id FROM events WHERE events.referrer_id = 1470 AND events.company_id IS NULL AND events.person_id = people.id AND events.event_kind_id = 9 ORDER BY created_at DESC LIMIT 1) event_kind_9, 
     (SELECT events.id FROM events WHERE events.company_id IS NULL AND events.person_id = people.id AND events.event_kind_id = 10 ORDER BY created_at DESC LIMIT 1) event_kind_10, 
     (SELECT events.created_at FROM events WHERE events.referrer_id = 1470 AND events.company_id IS NULL AND events.person_id = people.id AND events.event_kind_id = 9 ORDER BY created_at DESC LIMIT 1) event_kind_9_order 
FROM "people" 

SELECT employees.id, 
     employees.company_id, 
     employees.person_id, 
     (SELECT events.id FROM events WHERE events.referrer_id = 1470 AND events.company_id = employees.company_id AND events.person_id = employees.person_id AND events.event_kind_id = 9 ORDER BY created_at DESC LIMIT 1) event_kind_9, 
     (SELECT events.id FROM events WHERE events.company_id = employees.company_id AND events.person_id = employees.person_id AND events.event_kind_id = 10 ORDER BY created_at DESC LIMIT 1) event_kind_10, 
     (SELECT events.created_at FROM events WHERE events.referrer_id = 1470 AND events.company_id = employees.company_id AND events.person_id = employees.person_id AND events.event_kind_id = 9 ORDER BY created_at DESC LIMIT 1) event_kind_9_order 
FROM "employees" 

我寧願懷疑我做錯了。應該有一個「更容易」的方式來做到這一點。

另一個過濾標準是過濾人員/公司名稱:WHERE LOWER(companies.name)LIKE'%apple%'。

請注意,我在這裏按event_kind_9的日期排序,而次排序按人/公司名稱排序。總結:我希望對結果集進行分頁,找到每個單元格的最新事件,按照最新事件的日期排序結果集,並按公司/人員名稱,在某些事件類型中按引用來過濾,但不是其他人。

作爲參考,我使用PostgreSQL,從Ruby,ActiveRecord/Rails。儘管解決方案是純SQL。

回答

1

對於同一個人/公司和event_kind_id是否可以有多行(例如,比爾蓋茨在07年3月和09年3月打了電話)?如果沒有,你可以這樣做:

Select Coalesce(People.name, Companies.name) As Name 
    , Referrers.name 
    , Min(Case When EventKinds.name = 'Phoned' Then Events.created_at End) As Phoned 
    , Min(Case When EventKinds.name = 'Promised' Then Events.created_at End) As Promised 
    , Min(Case When EventKinds.name = 'Donated' Then Events.created_at End) As Donated 
From Events 
    Join EventKinds 
     On EventKinds.id = Events.event_kind_id 
    Left Join People As Referrers 
     On Referrers.id = Events.referrer_id 
    Left Join People 
     On People.id = Events.person_id 
    Left Join Companies 
     On Companies.id = Events.company_id 
-- Where Companies.Name Like 'foo%' 
Group By Coalesce(People.name, Companies.name), Referrers.name 
+0

我只需要每個事件類型的最新事件。抱歉,遲到的接受。 – 2010-12-19 00:31:50