SQL server:复杂的左连接查询

时间:2018-02-01 10:57:35

标签: sql-server join

有2个表:

people

+------------+--------------+------+
| name       | place        | pid  |
+------------+--------------+------+
| Mr John    | place1       |    1 |
| Miss Smith | place2       |    2 |
+------------+--------------+------+


places

+------+------+----------------------+
| pid  | owner| address              |
+------+------+----------------------+
|    1 |    1 | address1             |
|    1 | null | address2             |
|    2 | null | address3             |
|    2 | null | address4             |
|    2 | null | address5             |
+------+------+----------------------+

我正在寻找一个将返回的查询:

people (complex left join) places on people.pid = places.pid

Mr John    | place1 | 1 | 1 | 1    | address1
Miss Smith | place2 | 2 | 2 | null | address3
Miss Smith | place2 | 2 | 2 | null | address4
Miss Smith | place2 | 2 | 2 | null | address5

单词pid上的联接,但如果特定owner存在非空person值,则只获取该行,如果不存在非空{{1}然后获取特定owner的所有行。使用左连接,因为我还需要person people

2 个答案:

答案 0 :(得分:3)

一种策略是预先处理CTE中的places表,以确定哪个pid组记录至少有一个非NULL所有者值。此类pid记录需要全部包含在联接中。另一方面,如果pid群组至少有一位非NULL所有者,那么我们只会在联接中包含非NULL个匹配项。

WITH cte AS (
    SELECT pid, owner, address,
        SUM(CASE WHEN owner IS NOT NULL THEN 1 ELSE 0 END) OVER
            (PARTITION BY pid) AS non_null_cnt
    FROM places
)

SELECT t1.name, t1.place, t1.pid, t2.owner, t2.address
FROM people t1
LEFT JOIN cte t2
    ON t1.pid = t2.pid AND
       (t2.owner IS NOT NULL OR t2.non_null_cnt = 0)
ORDER BY t1.pid;

enter image description here

Demo

答案 1 :(得分:1)

;WITH CTE as
(
  SELECT count(owner)over(partition by pid) mo,*
  FROM places
)
SELECT *
FROM people p
LEFT JOIN CTE
ON
  p.pid = CTE.pid
  and (mo = 0
       or owner is not null)