如何使列中的条目显示为行标题
Posted
技术标签:
【中文标题】如何使列中的条目显示为行标题【英文标题】:How to make entries from column appear as row title 【发布时间】:2021-07-22 09:52:56 【问题描述】:我有一个类似这样的医院数据库
id | patient_name | admitDate | DischargeDate |RoomCategory
1 | john |3/01/2011 | 5/01/2011 |Category1
2 | lisa |3/01/2011 | 4/01/2011 |Category2
3 | ron |5/01/2011 | 10/01/2011 |Category1
4 | howard |6/01/2012 | 10/01/2012 |Category3
5 | john |6/05/2011 | 7/05/2011 |Category4
6 | rammy |6/02/2011 | 7/03/2011 |Category4
我要计算每天住院病人的数量(入院和出院日期都要计算),并按类别分组
假设在 2011 年 3 月 1 日,我们有 2 名患者,一名在 1 类,一名在 2011 年 4 月 1 日,我们再次有相同的 2 名患者,但在 2011 年 5 月 1 日,丽莎(id 2)出院所以我们只有 1 名 1 类患者,但现在 ron (id 3) 也入院了,所以现在我们也必须算上他。
输出应该是这样的
Date | Category1 | Category2 | Category3 |Category4
3/01/2011 | 1 | 1 | 0 | 0
4/01/2011 | 1 | 1 | 0 | 0
5/01/2011 | 2 | 0 | 0 | 0
我不知道如何列出所有可能有病人的日期,因为实际表格很大,而且很多日期都没有病人。我也无法知道我将如何区分每个类别的计数。
我的实际表格中总共有 15 个类别,因此单独为每个类别使用 where 效率不会很高。
【问题讨论】:
我没有“删除”它,您无法评论已删除的问题。至于不能用PIVOT
那就用条件聚合吧。我再次为您打开了这个,但这只是上面的副本。
@Larnu 谢谢你的打开,我正在阅读你发送的链接,也许他们有帮助
@Larnu 我觉得问题已经死了,浏览量没有增加:(
21 分钟后……真的……?请耐心等待...由于您发布了您的问题,仅发布了 1 个与 SQL Server 相关的问题...Stack Overflow 不是免费的编码服务,请不要将其视为免费。
【参考方案1】:
这里有 2 个问题。 1 你需要一个日历表,然后 2 一个数据透视表。我建议,老实说,您首先投资创建日历表,但我在这里使用内联表。然后,您可以使用透视将值转换为列。我在这里使用条件聚合,因为它是可转移的并且限制较少。
SELECT *
INTO dbo.YourTable
FROM (VALUES(1,'john ',CONVERT(date,'3/01/2011'),CONVERT(date,'5/01/2011 '),'Category1'),
(2,'lisa ',CONVERT(date,'3/01/2011'),CONVERT(date,'4/01/2011 '),'Category2'),
(3,'ron ',CONVERT(date,'5/01/2011'),CONVERT(date,'10/01/2011'),'Category1'),
(4,'howard',CONVERT(date,'6/01/2012'),CONVERT(date,'10/01/2012'),'Category3'),
(5,'john ',CONVERT(date,'6/05/2011'),CONVERT(date,'7/05/2011 '),'Category4'),
(6,'rammy ',CONVERT(date,'6/02/2011'),CONVERT(date,'7/03/2011 '),'Category4'))V(id,patient_name,admitDate,DischargeDate,RoomCategory)
GO
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT 0 AS I
UNION ALL
SELECT TOP (SELECT DATEDIFF(DAY, MIN(admitDate), MAX(DischargeDate)) FROM dbo.YourTable)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3), --UP to 1000 days. Add more cross joins for more days
Calendar AS(
SELECT DATEADD(DAY, T.I, YT.MinAdmitDate) AS D
FROM Tally T
CROSS APPLY (SELECT MIN(admitDate) AS MinAdmitDate FROM dbo.YourTable) YT)
SELECT C.D AS [Date],
COUNT(CASE YT.RoomCategory WHEN 'Category1' THEN 1 END) AS Category1,
COUNT(CASE YT.RoomCategory WHEN 'Category2' THEN 1 END) AS Category2,
COUNT(CASE YT.RoomCategory WHEN 'Category3' THEN 1 END) AS Category3,
COUNT(CASE YT.RoomCategory WHEN 'Category4' THEN 1 END) AS Category4
FROM Calendar C
LEFT JOIN dbo.YourTable YT ON C.D >= YT.admitDate
AND C.D <= DischargeDate
GROUP BY C.D;
GO
DROP TABLE dbo.YourTable;
db<>fiddle 请注意,结果可能不是您所期望的,因为 DB Fiddle 默认为美式,并且您提供了不明确的日期格式,而我没有在 CONVERT
函数中提供明确的样式。
【讨论】:
以上是关于如何使列中的条目显示为行标题的主要内容,如果未能解决你的问题,请参考以下文章
如何检查一系列字符串是不是包含在 PANDAS DataFrame 列中并将该字符串分配为行中的新列?
当必须使用同一列中的不同值填充单元格时,如何填写该列中的空白单元格?