我想先说一句,我知道这很疯狂。
我继承了一个必须维护的应用程序,该应用程序来自某个人,该人将6组列反规范化为一行(例如一些核心列,如 ID、00_c1、00_c2、00_c3、01_c1、01_c2、01_c3、02_c1、02_c2、02_c3 等)。
然后,他想重新规范化这些列集,以便从行中创建 json 对象。
在最初的实现中,他编写了一个重新规范化的视图,使用了 6 个 UNION ALL
例如
SELECT ID, '0' as X, 00_c1 as c1, 00_c2 as c2, 00_c3 as c3
FROM table WHERE 00_c1 is not null
UNION ALL
SELECT ID, '1' as X, 01_c1 as c1, 01_c2 as c2, 01_c3 as c3
FROM table WHERE 01_c1 is not null
UNION ALL
SELECT ID, '2' as X, 02_c1 as c1, 02_c2 as c2, 02_c3 as c3
FROM table WHERE 02_c1 is not null
UNION ALL
...
他的 JSON 化查询查找 ID 上的行,然后使用 FOR JSON PATH 连接到 ID 上的视图。
它非常低效,所以我试图用 CROSS APPLY (VALUES ()) 代替规范化
它起作用了,并且效率更高,但是在 VALUES 实现中我得到了一个奇怪的问题,其中一组中的所有列都为空,并且我得到了一个空的 json 对象。
换句话说,并非所有行都包含所有 6 组列。有些可能有 3 组,有些有 4 组,等等,并且 (05_c1、05_c2、05_c3) 列将全部为空。该行的结果 json 仅显示为 {}
有没有什么方法(使用 FOR JSON 或 VALUES)可以忽略所有值为空的行?
或者唯一真正的解决方案是通过适当的规范化来重新实现整个事物?
我找到了解决方法。这有点尴尬,但我保留了子查询和并集,但外部查询建立了行上下文。看起来很复杂,但确实有效: