2010-01-21 85 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