2

我使用通过 java JDBC 连接到的HSLQDB (2.2.9) 数据库。

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 字符串中使用 JOIN 构建查询?

我发现PIVOT函数是我需要的,但似乎 HSQLDB 不支持它并且搜索 stackoverflow 和谷歌并没有带来有用的信息。

感谢您提供任何信息

4

2 回答 2

0

PIVOT is not standard SQL, it's an extension to syntax supported only by Microsoft SQL Server 2005 (and later), and Oracle 11g.

Here's a solution that uses standard SQL and should work in any 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;

Re your comment:

SQL does not allow data values to generate new columns dynamically in the same query. So any pivot query requires that you know how many distinct vaccinations you want to show in the output before you prepare the query.

You could run two queries: one to "discover" the set of distinct vaccination values:

SELECT DISTINCT ID_Vaccination FROM ValuesVaccination;

Then fetch that back into the application and loop over it, adding column expressions as you go, to build the pivot query.

The only alternative is to fetch all the data joined to Students, as in your first query, and post-process it into a pivoted format using application code.

Either way, to produce a dynamic pivot query you have to supplement it with application code, either before you prepare the query or after you fetch the results.

于 2013-01-09T00:52:51.327 回答
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

返回想要的结果。

于 2013-01-09T18:42:20.100 回答