根据序数和属性数据选择前n个记录

时间:2012-04-11 18:53:38

标签: sql-server sql-server-2008 tsql

我有一个案例,我需要根据表格中的设置和序数集只显示顶行。

下面的示例数据集显示了两个客户;每个客户都有不同的产品。 由于NumRowsToShow为“1”,我只想为每个客户显示一行(基于序数的顶行)。

| CustomerID | ProductID | Ordinal | NumRowsToShow |
+------------+-----------+---------+---------------+
| 1          |A          |1        |1              |
| 1          |B          |2        |1              |
| 1          |C          |3        |1              |
| 5          |D          |1        |1              |
| 5          |E          |2        |1              |
| 5          |F          |3        |1              |

运行查询后的结果集应为

| CustomerID | ProductID |
+------------+-----------+
| 1          |A          |
| 5          |D          |

在同一场景中,NumRowsToShow对于customerID 1为1,对于CustomerID 5为2,我会看到类似的内容。

| CustomerID | ProductID | Ordinal | NumRowsToShow |
+------------+-----------+---------+---------------+
| 1          |A          |1        |1              |
| 1          |B          |2        |1              |
| 1          |C          |3        |1              |
| 5          |D          |1        |2              |
| 5          |E          |2        |2              |
| 5          |F          |3        |2              |

运行查询后的结果集应为

| CustomerID | ProductID |
+------------+-----------+
| 1          |A          |
| 5          |D          |
| 5          |E          |

如何做到这一点?

包含实际结果集的屏幕上限,其中包含我想要过滤的内容的重点,这可能会有所帮助。

Screencap http://www.harpernet.net/se/cap01.jpg

1 个答案:

答案 0 :(得分:6)

感觉像是在考试中作弊":

SELECT CustomerID, ProductID
FROM tableX
WHERE Ordinal <= NumRowsToShow

如评论所示,Ordinal可以有10, 20, 30个值,而不仅仅是1, ..., n个值,那么这将有效:

SELECT t.CustomerID, t.ProductID
FROM tableX AS t
  JOIN tableX AS tt
    ON  tt.CustomerID = t.CustomerID
    AND tt.Ordinal <= t.Ordinal
GROUP BY t.CustomerID
       , t.ProductID
       , t.NumRowsToShow
HAVING COUNT(*) <= t.NumRowsToShow

甚至更好,:

SELECT CustomerID, ProductID
FROM
  ( SELECT CustomerID, ProductID, NumRowsToShow
         , ROW_NUMBER() OVER( PARTITION BY CustomerID 
                              ORDER BY Ordinal
                            ) AS Rn
    FROM tableX
  ) AS tmp
WHERE Rn <= NumRowsToShow ;

测试:SQL-Fiddle


您的表看起来没有标准化。 NumRowsToShow列具有重复信息,可能导致更新异常。这样:

| CustomerID | ProductID | Ordinal | NumRowsToShow |
+------------+-----------+---------+---------------+
| 1          |A          |1        |1              |
| 1          |B          |2        |1              |
| 1          |C          |3        |1              |
| 5          |D          |1        |2              |
| 5          |E          |2        |2              |
| 5          |F          |3        |2              |

可以归一化为2个表:

| CustomerID | ProductID | Ordinal |
+------------+-----------+---------+
| 1          |A          |1        |
| 1          |B          |2        |
| 1          |C          |3        |
| 5          |D          |1        |
| 5          |E          |2        |
| 5          |F          |3        |

| CustomerID | NumRowsToShow |
+------------+---------------+
| 1          |1              |
| 5          |2              |