选择总计,如果已读

时间:2018-08-14 16:08:06

标签: sql sql-server sql-server-2012

我有下表:

Id Title 
1  Test

BookPage(BookId对应于Book表中的ID)

Id BookId Page
1  1      1
1  1      2

BookUserPage(BookPageId对应于BookPage表中的ID)

UserId BookPageId
1      1
2      2
3      1

我的选择查询如下:

SELECT B.[Id], B.[Title], BP.[Id], BP.[BookId], BP.[Page], COUNT(BUP.[BookpageId]) AS Total
FROM [Book] B
    LEFT OUTER JOIN [BookPage] BP ON BP.[BookId] = B.[Id]
    LEFT OUTER JOIN [BookUserPage] BUP ON BUP.[BookPageId] = BP.[Id]
WHERE B.[Id] = 1
GROUP BY B.[Id], B.[Title], BP.[Id], BP.[BookId], BP.[Page]

我得到的结果如下:

Id, Title, Id, BookId, Page, Total
1   Test   1,  1,      1,    2
1   Test   2,  1,      1,    1

我正在尝试修改查询,以便它还会告诉我用户阅读了2页中的哪一页。

我尝试了以下方法:

SELECT B.[Id], B.[Title], BP.[Id], BP.[BookId], BP.[Page], COUNT(BUP.[BookpageId]) AS Total,
CASE WHEN EXISTS (
    SELECT BUP2.[UserId] 
    FROM [PollUserAnswer] BUP2
    WHERE BUP2.[UserId] = '98ad813b-cd0e-4a63-b40a-e09ee84f4b96')
THEN 1
ELSE 0
END AS Voted
FROM [Book] B
    LEFT OUTER JOIN [BookPage] BP ON BP.[BookId] = B.[Id]
    LEFT OUTER JOIN [BookUserPage] BUP ON BUP.[BookPageId] = BP.[Id]
WHERE B.[Id] = 1
GROUP BY B.[Id], B.[Title], BP.[Id], BP.[BookId], BP.[Page]

但是上面的代码在我的结果的两行都加上了1。我还尝试过在Case语句中添加条件:

AND BUP2.[BookPageId] = BUP.[PageId]

但是由于分组依据而无法正常工作,我无法将其作为子查询在分组依据中列出。

我对用户1和3的期望输出是这样的:

Id, Title, Id, BookId, Page, Total, Read
1   Test   1,  1,      1,    2,     1
1   Test   2,  1,      1,    1,     0

我对用户2的期望输出是这样的:

Id, Title, Id, BookId, Page, Total, Read
1   Test   1,  1,      1,    2,     0
1   Test   2,  1,      1,    1,     1

注意:请忽略以下事实:查询输出中有2个Id列。

1 个答案:

答案 0 :(得分:1)

我将加入到单独的子查询中,以找到阅读给定页面的用户总数。然后,您只需要在BookUserPage的另一个左联接上进行标记即可生成Read列:

SELECT b.Id, b.Title, bp.Id, bp.BookId, bp.Page, bup1.total,
    CASE WHEN bup2.UserId IS NULL THEN 0 ELSE 1 END AS [Read]
FROM Book b
LEFT JOIN BookPage bp
    ON bp.BookId = b.Id
LEFT JOIN
(
    SELECT BookPageId, COUNT(*) AS total
    FROM BookUserPage
    GROUP BY BookPageId
) bup1
    ON bup1.BookPageId = bp.Id
LEFT JOIN BookUserPage bup2
    ON bup2.BookPageId = bp.Id AND bup2.UserId = 1
WHERE b.Id = 1;

Demo

这不会产生您期望的结果,但是考虑到您的实际样本数据和连接逻辑,这似乎在逻辑上是正确的。