Вернуть первый не нулевой результат из столбца - PullRequest
1 голос
/ 12 июля 2019

В SQL Server у меня есть следующий запрос (свернутый):

SELECT A.ID, A.OWNER, B.CAR
FROM TABLE A
LEFT JOIN TABLE B ON A.ID = B.CAR_ID

, который возвращает следующее:

ID   Owner   Car
01   Bob     BMW
02   Bob     NULL
03   Bob     BMW
04   Andy    Audi
05   Andy    Audi

Я хочу сгруппировать по владельцу с первым не NULLрезультат для машины:

Owner   Car
Bob     BMW
Andy    Audi

Я мог бы сделать:

SELECT A.OWNER, max(B.CAR) as Car
FROM TABLE A
LEFT JOIN TABLE B ON A.ID = B.CAR_ID
GROUP BY A.OWNER

Но есть ли способ сделать это с Coalesce ()?Или что-то еще, что может работать лучше с более сложным запросом?

Ответы [ 3 ]

1 голос
/ 12 июля 2019

Когда автомобиль присутствует, ваш набор результатов всегда ассоциирует «Боб» с «BMD» и «Энди» с «Audi». Я предполагаю, однако, что в реальном наборе данных есть владельцы, которые могут иметь более одного типа автомобилей. Таким образом, возникает вопрос: «какой из них вы выбираете?».

Если это действительно произвольно и не имеет значения, тогда ваш существующий подход, использующий 'max', подойдет. По крайней мере, он имеет предсказуемый порядок по умолчанию, так что вы будете получать один и тот же вывод при каждом прогоне при одинаковом состоянии данных в базовых таблицах.

Однако, если что-то еще должно считаться «первым», например, если вы хотите основать сравнение на поле «id», то вы захотите использовать «row_number» для упорядочения по этому полю для внутри каждый владелец, как в коде ниже.

select      owner, car
from        (
                select      *, 
                            ord = row_number() over(partition by owner order by id)
                from        [Table A] a
                left join   [Table B] b on a.id = b.car_id
                where       b.car is not null
            ) orderings
where       ord = 1
1 голос
/ 12 июля 2019

Вы можете сделать следующее:

SELECT TOP 1 WITH TIES A.OWNER, B.CAR
FROM TABLE A
LEFT JOIN TABLE B ON A.ID = B.CAR_ID
ORDER BY ROW_NUMBER() OVER (PARTITION BY A.OWNER ORDER IIF(B.CAR IS NOT NULL, 0, 1), A.ID)

Разбивая ORDER BY на две части, вы помещаете все последние NULL с последующим упорядочением по указанному идентификатору в вашем наборе результатов.Каждый отдельный A.OWNER получит ROW_NUMBER() 1. Используя TOP 1 WITH TIES, вы останетесь со всеми 1 без использования подзапроса, таким образом, имея только одну строку на A.OWNER.

1 голос
/ 12 июля 2019

Я не уверен, что вы подразумеваете под первым результатом.Если вы хотите перейти по порядку по умолчанию, вы можете сделать следующее: Если вы заказываете по идентификатору, то это будет

SELECT DISTINCT FIRST_VALUE(Owner) OVER(PARTITION BY Owner ORDER BY ID), FIRST_VALUE(Car) OVER(PARTITION BY Owner ORDER BY ID)
FROM Table_Name WHERE Car IS NOT NULL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...