【发布时间】:2019-11-18 16:59:13
【问题描述】:
考虑以下表格
书
[Id], [Name], [DatePublished]
1 Test One, 2019-01-01 00:00:00.000
2 Test Two 2019-01-02 00:00:00.000
3 Test Three 2019-01-02 00:00:00.000
标签
[Id], [Name]
1 TagOne
2 TagTwo
3 TagThree
书名
[BookId], [TagId]
1 1
1 2
1 3
2 1
2 2
3 3
我想选择前两本书及其所有相关标签的示例,您可以按照自己的喜好订购它们,那部分无关紧要。
这是我尝试过的
SELECT *
FROM (
SELECT *, 1 AS SplitOn,
(ROW_NUMBER() OVER(ORDER BY [Id] ASC)) AS RowNumber, COUNT(*) over() as TotalRows
FROM (
SELECT B.[Id], B.[Name], B.[DatePublished], T.[Id] AS TagId, T.[Name] AS TagName
FROM [Book] B
LEFT OUTER JOIN [BookTag] BT ON BT.[BookId] = B.[Id]
LEFT OUTER JOIN [Tag] T ON T.[Id] = BT.[TagId]
)
)
WHERE RowNumber BETWEEN 1 AND 2
现在上述查询的问题是它会给每一行一个唯一的行号,因此我总是只会得到前 2 行。我真正想要的是前 2 本书 ID 的每一行。我不太清楚如何使用分区来做到这一点。这可以使用 Row_Number 还是我必须做一些完全不同的事情?
编辑:如果可能的话,我想用 row_number 和 partition 来完成。不透露一些敏感信息就很难解释原因。最好我可以将其描述为使用子查询没有多大意义,因为我上面给出的示例非常简化为实际场景。实际场景中的查询要复杂得多。
预期结果示例一(按 Id ASC 排序):
[Id], [Name], [DatePublished], [TagId], [TagName], [SplitOn], [RowNumber]. [TotalRows]
1 Test One 2019-01-01 00:00:00.000 1 TagOne 1 1 3
1 Test One 2019-01-01 00:00:00.000 2 TagTwo 1 1 3
1 Test One 2019-01-01 00:00:00.000 3 TagThree 1 1 3
2 Test Two 2019-01-02 00:00:00.000 1 TagOne 1 2 3
3 Test Two 2019-01-02 00:00:00.000 2 TagTwo 1 2 3
预期结果示例二(按日期 DESC 排序):
[Id], [Name], [DatePublished], [TagId], [TagName], [SplitOn], [RowNumber]. [TotalRows]
3 Test Three 2019-01-02 00:00:00.000 3 TagThree 1 1 3
2 Test Two 2019-01-02 00:00:00.000 1 TagOne 1 2 3
2 Test Two 2019-01-02 00:00:00.000 2 TagTwo 1 2 3
【问题讨论】:
-
如何定义“前两本书”?
-
@GordonLinoff 您可以随意对它们进行排序,因为这并不重要。前两个我的意思是使用这本书的 ID。
-
您的预期结果是什么?
-
@GenWan 更新问题
-
@Bojan 为什么书名 3 的名字是测试二?
标签: sql sql-server sql-server-2014