有效的SQL查询,以1-N关系查找第一个(按日期)关联记录

时间:2009-06-10 07:24:18

标签: sql-server-2005 tsql

以下是该场景:有一个软件表(PK = SoftwareID)和一个关联的Release表(PK = [SoftwareID,Version])。

版本可以是主要版本或次要版本,版本类型由Release.ReleaseType('MAJ','MIN')标识。

版本的特征还有日期:Release.ReleaseDate。

软件按类别划分,由Software.CategoryID标识。

问题:需要一个有效 T-SQL查询来列出某个类别的所有软件,并且第一个主要发布日期在给定的时间间隔内,由@DateFrom,@ DateTo分隔。最终结果集中唯一需要的列是SoftwareID和ReleaseDate。

这不是真实情况,但我这样制定它更容易理解。在实际案例中,表格Release将有大约1000万条记录,表格软件大约有100万条。我已经找到了一个解决方案,但它很慢,我觉得这里的专家可能会找到更好的东西。

这是我的慢解决方案:

select  s.SoftwareID, min(r.ReleaseDate)
from
    Software s inner join Release r on (s.SoftwareID = r.SoftwareID)
where s.CategoryID = @Category
      and r.ReleaseType = 'MAJ'
group by
    s.SoftwareID
having
    min(r.ReleaseDate) >= @DateFrom
    and min(r.ReleaseDate) < @DateTo

感谢。

4 个答案:

答案 0 :(得分:2)

您的查询很好。

您可能希望确保查询具有正确的索引:

  • 在“MSSQL Management Studio”中:“查询” - &gt;“分析数据库引擎优化顾问中的查询”,然后按照“白兔”(首选)
  • 在“MSSQL Management Studio”中:“查询” - &gt;“包括实际执行计划”。然后运行查询,查看执行计划是否建议新索引。

答案 1 :(得分:1)

您可能遇到索引问题。您是否尝试在ReleaseDate列上创建索引或在包含ReleaseDate的表上创建聚簇索引(按ReleaseDate排序)?

答案 2 :(得分:1)

尝试以下方面的内容:

select  
  s.SoftwareID, 
  min(r.ReleaseDate)
from
  Software s 
  inner join Release r on s.SoftwareID = r.SoftwareID
where 
  s.CategoryID = @Category
  and r.ReleaseType = 'MAJ'
  and s.ReleaseDate >= @DateFrom
  and s.ReleaseDate < @DateTo
group by
  s.SoftwareID

基本思路是:为什么在分组后过滤日期,以防止不需要的记录在分组之前输入结果

您正在s.SoftwareID进行分组。对我而言,似乎HAVING MIN(s.ReleaseDate) >= ...无法影响与WHERE s.ReleaseDate >= ...不同的记录。

答案 3 :(得分:1)

谢谢大家的建议。问题似乎几乎已经解决,我认为没有太多工作要做。

查询顾问建议了两个有用的索引,其中一个类似于:

CREATE NONCLUSTERED INDEX [IX_Release_1234] ON [dbo].[Release] 
(
    [ReleaseType] ASC,
    [SoftwareID] ASC
)
INCLUDE ( [ReleaseDate]) WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]

索引调整将执行时间减少到不到50%。但是,另一个轻微的改进(之前减半时间的25-30%)是重新组织查询,首先从Release表中获取发布日期,然后将此子查询与Software连接:

select s.SoftwareID, r.ReleaseDate
from Software s inner join (
    select   SoftwareID, min(ReleaseDate) as ReleaseDate
    from     Release
    where    ReleaseType = 'MAJ'
    group by SoftwareID
    having
        min(ReleaseDate) >= @DateFrom
        and min(ReleaseDate) < @DateTo
) r on (
    s.SoftwareID = r.SoftwareID
)
where
    s.CategoryID = @Category

现在我猜索引调整应该重做:)...

最重要的是,尽可能使用引擎调整顾问,再次感谢大家。