我有一个案例,我需要根据表格中的设置和序数集只显示顶行。
下面的示例数据集显示了两个客户;每个客户都有不同的产品。
由于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 |
如何做到这一点?
包含实际结果集的屏幕上限,其中包含我想要过滤的内容的重点,这可能会有所帮助。
答案 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 |