2010-01-21 138 views
2

我爲小型CRM系統進行了數據庫設計。它由公司和會議(包括其他)組成。我的SQL加入/羣組/光標問題時遇到問題

公司具有以下字段: ID(初級,auto_inc) 名稱(文本)

會議有以下字段: ID(初級,auto_inc) CompanyId(鏈接到Companies.ID) WhenTime(日期時間,以便在會議時存儲) 備註(有關會議的文本)

我想完成的是一個查詢,該查詢給出了所有公司(表中所有字段)的列表,以及WhenTime和Notes與該公司的最新會議(最新是最大(WhenTime),如果沒有,則是a NULL會很好)。

我想我可以用光標解決這個問題,但是我害怕速度。

我已經嘗試了幾組按配方,但我擔心我缺乏所需的技巧。

我的最後一次嘗試是這樣的:

select Companies.ID, Companies.name, mts.whentime, mts.notes 
from Companies 
left outer join (
    select top(1) * 
    from Meetings 
    order by [whentime] desc 
) mts 
on Companies.ID = mts.companyID 
order by Companies.name asc 

但是這個代碼只需從會議一個元組,在加入每家公司不是一個,所以一點也不好。

任何想法?

+0

你需要列出所有的公司,或者只有那些有過至少一次會議? – 2010-01-21 15:29:14

+0

所有公司,如果有最新的會議時間和東西 – Tominator 2010-03-25 16:06:26

回答

2

嘗試:

select Companies.ID, Companies.name, mts.whentime, mts.notes 
from Companies 
cross apply 
(
    select top(1) * 
    from Meetings 
    where Companies.ID = Meetings.companyID 
    order by [whentime] desc 
) mts 
order by Companies.name asc; 
+0

謝謝!我甚至不知道交叉應用存在... – Tominator 2010-01-21 11:04:57

+0

如果您想包括從未開過會議的公司,請使用OUTER APPLY而不是CROSS APPLY。 – 2010-01-21 22:51:29

2

我將通過創建最新會議的看法,因爲我覺得創建視圖啓動使得複雜的查詢更容易閱讀和維護,可以引入可重用的元素(如果使用得當)。

CREATE VIEW [dbo].[LatestCompanyNotes] 
AS 

SELECT [CompanyId], [WhenTime], [Notes] 
FROM [Meetings] AS M1 
INNER JOIN 
    (
     SELECT [CompanyId], MAX([Id]) AS [MaxId] 
     FROM [Meetings] 
     GROUP BY [CompanyId] 
    ) AS M2 ON M2.[CompanyId] = M1.[CompanyId] AND M2.[MaxId] = M1.[Id] 

現在,您應該能夠像以前一樣加入到您的查詢中的此視圖。

SELECT Companies.[ID], Companies.[Name], mts.[WhenTime], mts.[Notes] 
FROM [Companies] 
    LEFT OUTER JOIN [dbo].[LatestCompanyNotes] AS mts ON mts.[CompanyId] = Companies.[ID] 
ORDER BY Companies.[Name] ASC 

請注意,我沒有測試代碼(我甚至不安裝的SQL Server),它可能需要一些小的改動工作。

+0

謝謝你的回覆!但我與其他解決方案一起使用,因爲它更小,不需要視圖。 – Tominator 2010-01-21 11:05:56

+0

在底部重新記錄您的注意事項:您非常*近(令人印象深刻!)。我在視圖中修改了select(需要max(id)的別名,並且需要將公司ID包含在'on'子句中)。我已經測試過這個選擇,它可以工作。我也在明確的外部選擇中做了連接。 – 2010-01-21 11:12:14

+0

@提名者:凱恩的方法不需要*視圖,視圖只是簡化了視圖。它還具有不依賴於SQL Server特定功能的優點(交叉應用)。 – 2010-01-21 11:17:41

1

你不需要在這裏交叉應用,只是一個相關子查詢來查找最近的一次會議日期:

SELECT Companies.ID, Companies.name, mts.whentime, mts.notes 
FROM Companies 
LEFT OUTER JOIN Meetings mts 
ON Companies.ID = mts.companyID 
AND mts.WhenTime = 
(SELECT MAX(WhenTime) FROM Meetings mtshist WHERE mtshist.companyID = mts.companyID) 
ORDER BY Companies.name 

注意,這會檢索所有的企業,包括那些從來沒有有一個會議:

1 Alexander and co. 2010-01-04 some more notes 
2 Barnard Partnership 2010-01-03 NULL 
3 Collingwood Ltd. 2010-01-07 recent meeting 
4 Dimitri and sons NULL  NULL