Предположим, у меня есть такие данные
first_name last_name city
John Bon Jovi null
John Lennon null
John Deer null
И я хочу создать агрегирующий запрос, который будет возвращать json, который выглядит следующим образом
{ "first_name": "John", "city": null }
По сути, запрос должен проверить,в каждом столбце есть только одно отдельное значение, и если оно есть, поместите это значение в json. Все непустые столбцы относительно легко получить с помощью запроса, подобного следующему:
select
case when count(distinct first_name) = 1 then max(first_name) end as first_name,
case when count(distinct last_name) = 1 then max(last_name) end as last_name,
case when count(distinct city) = 1 then max(city) end as city
from ...
for json path, without_array_wrapper
или
select
case when max(first_name) = min(first_name) then max(first_name) end as first_name,
case when max(last_name) = min(last_name) then max(last_name) end as last_name,
case when max(city) = min(city) then max(city) end as city
from ...
for json path, without_array_wrapper
Результатом вышеупомянутых запросов является json, подобный этому {"first_name":"John"}
. Но тогда возникают проблемы с нулями. Проблема (1) - приведенные выше запросы не учитывают нулевые значения, поэтому, если у меня есть такие данные
first_name last_name city
----------------------------------
John Lennon null
John Lennon null
John null null
, тогда фамилия также включается в результирующий json
{ "first_name": "John", "last_name": "Lennon" }
Хорошо, это понятно (причина ...Null value is eliminated by an aggregate...
), и я могу решить его с помощью запроса, подобного следующему:
select
case when count(distinct first_name) = 1 and count(first_name) = count(*) then max(first_name) end as first_name,
case when count(distinct last_name) = 1 and count(last_name) = count(*) then max(last_name) end as last_name,
case when count(distinct city) = 1 and count(city) = count(*) then max(city) end as city
from ...
for json path, without_array_wrapper
Но есть и другие проблемы с нулями, которые я не могу решить аккуратно дляв настоящее время. Задача (2) - я хочу, чтобы в моем json также было "city":null
. Конечно, я могу сделать что-то вроде этого
...
case when count(city) = 0 then 'null' end as city
...
и затем заменить строку null
реальными нулями, но это не очень аккуратно. Еще одна неприятная вещь ( 3 ) - я бы очень хотел избавиться от предупреждений
Предупреждение: нулевое значение устраняется с помощью агрегата или другой операции SET.
без выключения ANSI_WARNINGS
. Пока я могу думать только об использовании некоторых заполнителей с isnull
, который не выглядит как чистое решение
...
case when count(distinct isnull(city, 'null')) = 1 then max(city) end as city
...
Итак, любые идеи о том, как элегантно решать проблемы ( 2 ) и ( 3 )? см. примеры в db<>fiddle
.