2

这在一个查询中可能是不可能的,但我想看看我的选择是什么。

我有一个大型查询,它返回每个库存的数据(在本例中为树)。该查询从几个不同的表中获取数据。我主要使用左外连接来引入这些信息,所以如果它不存在,我可以忽略它并取 NULL。我有一个有趣的情况,“树”和“害虫”之间存在一对多的关系。

  • 树表:treeID、treeHeight 等....
  • 害虫(害虫到树)表:害虫ID,树ID,害虫Ref.....

我需要一个查询来获取每棵树的前 6 种害虫并将它们作为列返回:

  • 害虫1、害虫2、害虫3……等等。

我知道我可以在多个查询中执行此操作,但是每次使用都会发生数千次,我们的服务器无法处理。

一些注意事项:我们使用的是ColdFusionMX7,我对存储过程的了解非常低。

4

1 回答 1

1

一种方法是按树生成表示害虫等级的列,然后将排名过的害虫表连接到以等级为连接条件的树表中。确保使用 ROW_NUMBER 而不是 RANK,因为平局会导致 RANK 中的数字重复(但不是 ROW_NUMBER),并确保使用 LEFT OUTER 连接,因此不会排除害虫较少的树。此外,我按 2 个条件排序,但在普通 ORDER BY 子句中有效的任何内容在这里都有效。

DECLARE @t TABLE (TreeID INT, TreeName VARCHAR(25));
DECLARE @p TABLE (PestID INT, TreeID INT, PestName VARCHAR(25));

INSERT INTO @t VALUES (1,'ash'),(2,'elm'),(3,'oak')
INSERT INTO @p VALUES (1,1,'ash borer'),(2,1,'tent catapilar'),(3,1,'black weevil'),(4,1,'brown weevil');
INSERT INTO @p VALUES (5,2,'elm thrip'),(6,2,'wooly adelgid');
INSERT INTO @p VALUES (7,3,'oak gall wasp'),(8,3,'asian longhorn beetle'),(9,3,'aphids');

WITH cteRankedPests as (
    SELECT PestID, TreeID, PestName, ROW_NUMBER() OVER (PARTITION BY TreeID ORDER BY PestName,PestID) as PestRank
    FROM @p 
)
SELECT T.TreeID, T.TreeName 
    , P1.PestID as P1ID, P1.PestName as P1Name
    , P2.PestID as P2ID, P2.PestName as P2Name
    , P3.PestID as P3ID, P3.PestName as P3Name
FROM @t as T 
    LEFT OUTER JOIN cteRankedPests as P1 ON T.TreeID = P1.TreeID AND P1.PestRank = 1
    LEFT OUTER JOIN cteRankedPests as P2 ON T.TreeID = P2.TreeID AND P2.PestRank = 2
    LEFT OUTER JOIN cteRankedPests as P3 ON T.TreeID = P3.TreeID AND P3.PestRank = 3
于 2014-07-01T15:23:10.133 回答