从列返回第一个非空结果

时间:2019-07-11 21:12:22

标签: sql sql-server

在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 个答案:

答案 0 :(得分:1)

我不确定您的意思是第一个结果。如果要按照默认顺序执行,可以执行以下操作: 如果您要按ID订购,那么应该是

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

答案 1 :(得分:1)

如果有汽车,则结果集始终将“ Bob”与“ BMD”关联,并将“ Andy”与“ 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

答案 2 :(得分:1)

您可以执行以下操作:

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的最后一个,然后在结果集中按给定的ID排序。每个不同的A.OWNER都将收到ROW_NUMBER()1。使用TOP 1 WITH TIES,您将得到全1,而不使用子查询,因此每个A.OWNER仅包含一行。