1

我有一个包含数据的表变量:

SiteID  DatabaseYear  CreationDate
1       2011          2012.01.01
2       2012          2012.06.06
3       2010          2010.10.10
1       2012          2012.07.07
3       2012          2012.07.27
4       2012          2012.08.31

在一个完美的世界里,我想像这样对结果进行排序:

SiteID  DatabaseYear  CreationDate
4       2012          2012.08.31
3       2012          2012.07.27
3       2010          2010.10.10
1       2012          2012.07.07
1       2011          2012.01.01
2       2012          2012.06.06

排序是这样的:获取最近创建日期的站点并首先显示它(按 CreationDate desc 排序),然后获取该站点的所有其他记录并按 DatabaseYear 显示它们(按 DatabaseYear desc 排序)。

当然,以下内容根本不起作用:

order by CreationDate desc, DatabaseYear desc

因为它将首先对整个结果集应用“CreationDate desc”,然后是“DatabaseYear desc”。

所以,我想出了一个光标,它执行以下操作:

  1. 获取最新的 SiteID
  2. 把它放在另一个表中(准确地说是表变量)
  3. 获取该 SiteID 的所有其他记录,按 DatabaseYear 降序排列
  4. 从第一个表中删除所有记录

问题:

如果第一个表有几千条记录,这个逻辑很有效,但是当有超过 5000 条左右时,它需要更长的时间。由于这是在网页上填充网格,我不能让用户等待超过 15-20 秒。在最坏的情况下(超过 40,000 条记录),执行需要 2-3 分钟。

任何建议将不胜感激。

4

2 回答 2

2

你需要更多地考虑集合,游标几乎永远不是正确的答案。您似乎更多地按照命令式程序员的思路思考。

这比最初看起来要简单得多:

WITH Most_Recent_Site (siteId, createdOn) as (SELECT id, MAX(createdOn)
                                              FROM Site_Data
                                              GROUP BY id)

SELECT Site_Data.id, Site_Data.createdOn
FROM Site_Data
JOIN Most_Recent_Site
ON Most_Recent_Site.siteId = Site_Data.id
ORDER BY Most_Recent_Site.createdOn DESC, Site_Data.createdOn DESC

我故意省略了“数据库年份”列,因为它似乎没有增加任何价值。

(而且我有一个有效的SQL Fiddle 示例。)

于 2012-08-06T15:43:13.653 回答
1
DECLARE @t TABLE  
(
  SiteID INT,  
  DatabaseYear INT,  
  CreationDate DATE
);

INSERT @t VALUES
(1,2011,'2012-01-01'),
(2,2012,'2012-06-06'),
(3,2010,'2010-10-10'),
(1,2012,'2012-07-07'),
(3,2012,'2012-07-27'),
(4,2012,'2012-08-31');

;WITH x AS 
(
  SELECT SiteID, d = MAX(CreationDate) 
     FROM @t
     GROUP BY SiteID
)
SELECT t.SiteID, t.DatabaseYear, t.CreationDate 
FROM @t AS t
INNER JOIN x 
ON t.SiteID = x.SiteID
ORDER BY x.d DESC, t.CreationDate DESC;
于 2012-08-06T15:34:19.673 回答