gpt4 book ai didi

sql - 在忽略重复项的同时计算子组的行

转载 作者:搜寻专家 更新时间:2023-10-30 19:40:09 25 4
gpt4 key购买 nike

我找不到以抽象和一般的方式描述我的问题的方法,所以我只提供一个最小的例子:

假设我有这 3 个简单的表格:

CREATE TABLE Document(
[Id] int IDENTITY(1, 1) NOT NULL PRIMARY KEY,
[Title] nvarchar(MAX),
[Patient] nvarchar(MAX)
);

CREATE TABLE Link(
DocumentId INT FOREIGN KEY REFERENCES Document(Id),
Text nvarchar(max)
);

CREATE TABLE ReadStatus(
DocumentId INT FOREIGN KEY REFERENCES Document(Id),
IsRead Bit NOT NULL,
UserId Int NOT NULL
);
  • 我们有一套文件
  • 一个文档可以有 0 个或多个链接
  • 文档可以被用户阅读 - 这由 ReadStatus 表跟踪,该表将用户与文档相关联,其中 IsRead=1 表示文档已被读取已被该用户阅读,IsRead=0 表示该用户尚未阅读。
  • 如果对于文档 X 和用户 AReadStatus 表中不存在一行,我们假设用户 A 尚未阅读文档 X

现在,我需要运行一个查询来选择所有患者。对于每位患者,我需要可用文档的总数和已阅读的文档数(即 IsRead=1)。这是我目前所拥有的:

SELECT d.Patient,
COUNT(DISTINCT d.Id) AS DocumentCount,
COUNT(NULLIF(rs.IsRead,0)) AS ReadDocumentCount,
COUNT(*) OVER () AS TotalPatientCount
FROM Document d
LEFT OUTER JOIN ReadStatus AS rs ON d.Id = rs.DocumentId AND rs.UserId = 123
INNER JOIN Link AS l ON d.Id = l.DocumentId AND l.Text IN ('Link W', 'Link X', 'Link T', 'Link Z')
GROUP BY d.Patient

当一份文档(已阅读)有多个链接时,就会出现此问题。如果该文档有 3 个链接,则 INNER JOIN 与链接表生成的笛卡尔积将导致 ReadDocumentCount 选择为 3 而不是 1。

换句话说,给定这个数据:

INSERT INTO Document(Title, Patient) VALUES('Doc A', 'Mike')
INSERT INTO Document(Title, Patient) VALUES('Doc B', 'Mike')

INSERT INTO Link(DocumentId, Text) VALUES(1, N'Link W')
INSERT INTO Link(DocumentId, Text) VALUES(1, N'Link X')
INSERT INTO Link(DocumentId, Text) VALUES(1, N'Link Y')
INSERT INTO Link(DocumentId, Text) VALUES(2, N'Link Z')

INSERT INTO ReadStatus(DocumentID, IsRead, UserId) VALUES(1, 1, 123)
INSERT INTO ReadStatus(DocumentID, IsRead, UserId) VALUES(2, 0, 123)

结果是:

Patient DocumentCount   ReadDocumentCount   TotalPatientCount
Mike 2 3 1

这就是我想要的:

Patient DocumentCount   ReadDocumentCount   TotalPatientCount
Mike 2 1 1

SQL fiddle :http://sqlfiddle.com/#!6/e06bf/3

最佳答案

您也可以有条件地使用 COUNT(DISTINCT):

SELECT d.Patient,
COUNT(DISTINCT d.Id) AS DocumentCount,
COUNT(DISTINCT (CASE WHEN rs.IsRead <> 0 THEN d.id END)) AS ReadDocumentCount,
COUNT(*) OVER () AS TotalPatientCount
FROM Document d LEFT OUTER JOIN
ReadStatus rs
ON d.Id = rs.DocumentId AND rs.UserId = 123 INNER JOIN
Link l
ON d.Id = l.DocumentId AND l.Text IN ('Link W', 'Link X', 'Link T', 'Link Z')
GROUP BY d.Patient;

关于sql - 在忽略重复项的同时计算子组的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34529295/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com