我正在使用 HSLQDB (2.2.9)数据库,我通过java JDBC连接到该数据库。
A人已接种疫苗1和3,B人已接种2和4。 使用这个简单的查询:
SELECT std.*,vac.Date FROM Students AS std
LEFT JOIN ValuesVaccination AS vac
ON vac.ID_Students = std.ID
我得到的结果集如下:
ID | Name | ID_Vaccination | Date
1 | PersonA | 1 | 2011-06-01
1 | PersonA | 3 | 2012-03-21
1 | PersonB | 2 | 2012-08-11
2 | PersonB | 4 | 2012-09-08
我想得到的是:
ID | Name | Vaccination1 | Vaccination2 | Vaccination3 | Vaccination4
1 | PersonA | 2011-06-01 | NULL | 2012-03-21 | NULL
2 | PersonB | NULL | 2012-08-11 | NULL | 2012-09-08
一种方法是:
SELECT std.*,
vac1.Date AS "Vaccination1",
vac2.Date AS "Vaccination2",
vac3.Date AS "Vaccination3",
vac4.Date AS "Vaccination4"
FROM Students AS std
LEFT JOIN ValuesVaccination AS vac1
ON vac1.ID_Students = std.ID AND vac1.ID_Vaccinations = 1
LEFT JOIN ValuesVaccination AS vac2
ON vac2.ID_Students = std.ID AND vac2.ID_Vaccinations = 2
LEFT JOIN ValuesVaccination AS vac3
ON vac3.ID_Students = std.ID AND vac3.ID_Vaccinations = 3
LEFT JOIN ValuesVaccination AS vac4
ON vac4.ID_Students = std.ID AND vac4.ID_Vaccinations = 4
问题是不同疫苗的数量是可变的。有没有一种不错的方法来实现这一点,而无需使用循环在java String中使用JOIN构建查询?
我发现 PIVOT 功能是我需要的,但似乎HSQLDB不支持它,搜索stackoverflow和谷歌没有提供有用的信息。
感谢您提供任何信息
答案 0 :(得分:0)
PIVOT
不是标准SQL,它只是Microsoft SQL Server 2005(及更高版本)和Oracle 11g支持的语法扩展。
这是一个使用标准SQL的解决方案,应该适用于任何RDBMS:
SELECT s.ID, s.Name,
MAX(CASE WHEN ID_Vaccination=1 THEN Date END) AS Vaccination1,
MAX(CASE WHEN ID_Vaccination=2 THEN Date END) AS Vaccination2,
MAX(CASE WHEN ID_Vaccination=3 THEN Date END) AS Vaccination3,
MAX(CASE WHEN ID_Vaccination=4 THEN Date END) AS Vaccination4
FROM Students AS s
LEFT JOIN ValuesVaccination AS v
ON s.ID = v.ID_Students
GROUP BY s.ID, s.Name;
重新评论:
SQL不允许数据值在同一查询中动态生成新列。所以 任何数据透视查询都要求您在准备查询之前知道要在输出中显示多少个不同的疫苗接种。
您可以运行两个查询:一个用于“发现”一组不同的疫苗接种值:
SELECT DISTINCT ID_Vaccination FROM ValuesVaccination;
然后将其提取回应用程序并循环遍历它,随时添加列表达式,以构建数据透视查询。
唯一的选择是获取所有加入Student的数据,如第一个查询中所示,并使用应用程序代码将其后处理为数据透视格式。
无论哪种方式,要生成动态数据透视查询,您必须在准备查询之前或在获取结果之后用应用程序代码补充它。
答案 1 :(得分:0)
比尔答案中END)
之后只有一个括号太多了。
要使用原始问题中的别名和列名称在此主题中获得100%正确答案:
SELECT std.ID, std.Name,
MAX(CASE WHEN v.ID_Vaccinations=1 THEN Date END) AS Vaccination1,
MAX(CASE WHEN v.ID_Vaccinations=2 THEN Date END) AS Vaccination2,
MAX(CASE WHEN v.ID_Vaccinations=3 THEN Date END) AS Vaccination3,
MAX(CASE WHEN v.ID_Vaccinations=4 THEN Date END) AS Vaccination4
FROM Students AS std
LEFT JOIN ValuesVaccination AS v
ON std.ID = v.ID_Students
GROUP BY std.ID, std.Name
返回所需的结果。