帮助SQL查询(加入视图?)

时间:2008-10-31 17:08:55

标签: sql

我有一个包含列的表

  

索引,日期

其中索引可能有多个日期,我的目标如下:选择一个看起来像

的列表
  

Index,MinDate,MaxDate

其中每个索引仅列出一次,而MinDate(MaxDate)表示整个表中该索引的最早(最新)日期 。这很容易,但是让我们限制此列表仅出现在给定日期范围内的索引。

到目前为止,我有以下内容:

SELECT 
    Index,
    MIN([Date]),
    MAX([Date])
FROM myTable
WHERE
    Index IN
    (SELECT Index From myTable WHERE [Date] BETWEEN '1/1/2000' AND '12/31/2000')
GROUP BY Index
ORDER BY Index ASC

这非常缓慢。有什么方法可以加快速度吗? [我正在运行SQL Server 2000。]

谢谢!

编辑:为了清晰起见。

8 个答案:

答案 0 :(得分:4)

我建议使用派生表方法。像这样:

SELECT 
     myTable.Index,
     MIN(myTable.[Date]),
     MAX(myTable.[Date])
FROM myTable
     Inner Join (
       SELECT Index 
       From myTable 
       WHERE [Date] BETWEEN '1/1/2000' AND '12/31/2000') As AliasName
       On myTable.Index = AliasName.Index
GROUP BY myTable.Index
ORDER BY myTable.Index ASC

编辑:进一步审核后,您可以通过其他方式创建此查询。以下查询可能在相同的时间内更快,更慢或执行。当然,这取决于表的索引方式。

Select [Index],
       Min([Date]),
       Max([Date])
From   myTable
Group By [Index]
Having Sum(Case When [Date] Between '1/1/2000' And '12/31/2000' Then 1 Else 0 End) > 0

在最佳情况下,此查询将导致索引扫描(而非搜索)过滤掉您不想显示的行。我鼓励你运行两个查询并选择最快的执行。

答案 1 :(得分:2)

我不是SQL Server专家,但如果您可以像这样进行子选择,则可能会更快。

SELECT Index,
  (SELECT MIN([Date] FROM myTable WHERE Index = m.Index),
  (SELECT MAX([Date] FROM myTable WHERE Index = m.Index)
From myTable m 
WHERE [Date] BETWEEN '1/1/2000' AND '12/31/2000'

答案 2 :(得分:1)

杰克,

我认为你可能需要针对这个问题采取不同的POV。

**Index, Min(Date), Max(Date)**选定的分组在一天中不会发生剧烈变化,与其涵盖的数据范围(可能是多年)相比

因此,一种选择是根据主表中的数据创建汇总表...例如

   SELECT 
       Index, 
       Min(Date) as MinDate, 
       Max(Date) as MaxDate
   INTO 
      MySummaryTable
   FROM 
      MyOriginalTable
   GROUP BY
      Index

可以通过sql作业在半常规(每日)基础上删除和重新创建此表。 同样,我会在它的id列上添加一个索引。

然后,当你需要运行你的每日查询时,

SELECT 
   summary.Index,
   summary.MinDate,
   summary.MaxDate
FROM
   MyOriginalTable mot
   INNER JOIN MySummaryTable summary
      ON mot.Index = summary.Index  --THIS IS WHERE YOUR CLUSTERED INDEX WILL PAY OFF
WHERE
   mot.Date BETWEEN '2000-01-01' AND '2000-12-31' --THIS IS WHERE A SECOND NC INDEX WILL PAY OFF

答案 3 :(得分:1)

这应该在两次表扫描中完成。

SELECT
     Index,
    MIN([Date]),
    MAX([Date])
FROM myTable
WHERE
    Index IN
    (SELECT Index From myTable WHERE [Date] BETWEEN '1/1/2000' AND '12/31/2000')
GROUP BY Index
ORDER BY Index ASC
OPTION (MERGE JOIN)

这是另一个查询。此查询获得不同的结果,而不是最初要求的结果。这将使所有具有与感兴趣的时段重叠的日期范围的索引(即使在该索引的感兴趣的时段中没有任何实际活动)。

SELECT
    Index,
    MIN([Date]),
    MAX([Date])
FROM myTable
GROUP BY Index
HAVING MIN([Date]) < '2001-01-01' AND MAX([Date]) >= '2000-01-01')
ORDER BY Index ASC

即使3在2000年没有数据,这将会回归。

3,1998-01-01,2005-01-01

答案 4 :(得分:0)

在日期列上放置聚簇索引会大大加快此查询的速度,但显然它可能会减慢当前其他快速运行的查询速度。

答案 5 :(得分:0)

你的解释不是很清楚:

  

其中每个索引仅列出一次,而MinDate(MaxDate)代表整个表中最早(最晚)的日期。

如果是这种情况,您应该返回两个结果集或存储答案,如:

DECLARE @MaxDate datetime, @MinDate datetime
SELECT
    @MinDate = MIN([Date]),
    @MaxDate = MAX([Date])
FROM myTable
--
SELECT
    [Index],
    @MinDate,
    @MaxDate
FROM myTable
WHERE [Date] BETWEEN '1/1/2000' AND '12/31/2000'

如果您想知道整个表格和[索引]的最小值/最大值,请尝试以下代码并结合前面的代码:

SELECT
    [Index],
    MIN([Date]) AS IndexMinDate,
    MAX([Date]) AS IndexMaxDate,
    @MinDate AS TableMinDate,
    @MaxDate AS TableMaxDate
FROM myTable
WHERE [Date] BETWEEN '1/1/2000' AND '12/31/2000'
GROUP BY [Index]
ORDER BY [Index] ASC

另请参阅索引列(如果可能)和查询计划。祝你好运。

答案 6 :(得分:0)

EXISTS运算符可能比子查询更快:

SELECT
     t1.Index,
     MIN(t1.[Date]),
     MAX(t1.[Date])
FROM
     myTable t1
WHERE
     EXISTS (SELECT * FROM myTable t2 WHERE t2.Index = t1.Index AND t2.[Date] >= '1/1/2000' AND t2.[Date] < '1/1/2001')
 GROUP BY
      t1.Index

这取决于我想的表大小和索引。我也喜欢G Mastros HAVING子句解决方案。

另一个重要的注意事项......如果您的日期实际上是DATETIME并且您的任何日期(现在或将来)都有时间组件,如果索引的日期为12,则可能会遗漏一些结果31/2000,除午夜之外还有任何时间。请记住一些事情。您也可以使用YEAR([Date])= 2000(假设MS SQL Server在这里)。我不知道数据库是否足够聪明,如果你这样做,那么在日期列上使用索引。

编辑:由于评论

,添加了GROUP BY并更改了日期逻辑

答案 7 :(得分:-1)

您不需要where子句中的子选择。此外,您可以将索引添加到日期列。表中有多少行?

SELECT
    [INDEX],
    MIN ( [Date] ),
    MAX ( [Date] )
FROM
    myTable
WHERE 
    [Date] Between '1/1/2000' And '12/31/2000'
GROUP BY
    [Index]
ORDER BY
    [INDEX] ASC