SELECT子查询中的NULL问题:多表关联实现工作日时长单行展示
嘿,我看你已经在尝试实现行转列的需求了——把每个工作模式的28天时长都展示在同一行里,天数不足的列返回NULL。你的子查询思路方向是对的,但有几个细节可以优化,我给你两种靠谱的实现方案:
首先先明确下我假设的表结构(如果和你的实际表有出入,替换成你的表名/字段名就行):
- 工作模式表:比如叫
pattern_table,包含pat_id(模式ID)、pat_nm(模式名称) - 每日时长表:比如叫
daily_hours_table,包含pat_id(关联模式ID)、pat_day_no(天数,1-28)、pat_day_hrs(当日时长)
方案1:条件聚合(通用SQL,兼容绝大多数数据库)
这种方式比写28个子查询更高效,也更容易维护:
SELECT pt.pat_nm AS 'Pattern Name', pt.pat_id AS 'Pattern ID', -- 为1到28天依次生成列,没有对应数据时返回NULL MAX(CASE WHEN dht.pat_day_no = 1 THEN FORMAT(dht.pat_day_hrs, 'HH:mm') END) AS 'Day 1', MAX(CASE WHEN dht.pat_day_no = 2 THEN FORMAT(dht.pat_day_hrs, 'HH:mm') END) AS 'Day 2', -- 这里省略Day3到Day27的代码,你直接复制上面的行修改数字即可 MAX(CASE WHEN dht.pat_day_no = 28 THEN FORMAT(dht.pat_day_hrs, 'HH:mm') END) AS 'Day 28' FROM pattern_table pt LEFT JOIN daily_hours_table dht ON pt.pat_id = dht.pat_id GROUP BY pt.pat_nm, pt.pat_id;
解释下这个方案的关键点:
- 用
LEFT JOIN保证所有模式都会被查询出来,哪怕某个模式没有任何天数的时长数据,所有Day列都会返回NULL CASE WHEN配合MAX聚合函数,把每行的天数数据转换成对应列的值——因为每个模式+天数只会有一条记录,用MAX或MIN都能拿到唯一值,没有对应天数的话CASE返回NULL,聚合后还是NULL- 如果你用的是MySQL,把
FORMAT换成TIME_FORMAT(dht.pat_day_hrs, '%H:%i');如果是Oracle,换成TO_CHAR(dht.pat_day_hrs, 'HH24:MI'),根据你的数据库调整格式化语法就行
方案2:修复你当前的子查询写法
如果你想继续用子查询的方式,必须补全两个关键细节,否则会出错:
SELECT tn.pat_nm AS 'Pattern Name', tn.pat_id AS 'Pattern ID', -- 每个子查询必须关联主查询的模式ID,并且限制只返回一行 (SELECT FORMAT(td.pat_day_hrs, 'HH:mm') FROM daily_hours_table td WHERE td.pat_id = tn.pat_id AND td.pat_day_no = 1 LIMIT 1) AS 'Day 1', -- MySQL用LIMIT 1,SQL Server用TOP 1,Oracle用WHERE ROWNUM=1 (SELECT FORMAT(td.pat_day_hrs, 'HH:mm') FROM daily_hours_table td WHERE td.pat_id = tn.pat_id AND td.pat_day_no = 2 LIMIT 1) AS 'Day 2', -- 继续复制到Day28即可 (SELECT FORMAT(td.pat_day_hrs, 'HH:mm') FROM daily_hours_table td WHERE td.pat_id = tn.pat_id AND td.pat_day_no = 28 LIMIT 1) AS 'Day 28' FROM pattern_table tn;
子查询的注意点:
- 必须加
td.pat_id = tn.pat_id:不然子查询会返回所有模式中第N天的第一条数据,而不是当前模式的 - 加行限制语法:比如
LIMIT 1,避免某个模式的某一天意外有多个记录时,子查询返回多行导致报错 - 如果你的模式表中
pat_id是唯一主键,那DISTINCT其实可以去掉——因为每个模式只会返回一行
另外补充个小提示:如果你的数据库支持PIVOT(比如SQL Server、Oracle),也可以用PIVOT语法实现,但条件聚合的兼容性更好,不用考虑数据库的特定语法差异。
内容的提问来源于stack exchange,提问作者Richard Slater
相关产品推荐
相关产品推荐

