SQL 联盟更喜欢来自一个 table 的记录?

SQL Union prefer records from one table?

我首先要说的是,我正在使用两个 table,它们的组织方式有点乱。我目前正在恳求我的案子对此进行调整,但无法控制它们。所以 tables 的组织是我无法控制的。

我有一个 table 看起来像这样

客户

| id | name | date_joined |
|----|------|-------------|
|  1 |  Bob |  2012-01-01 |
|  2 | Jack |  2012-01-01 |
|  3 | Jill |  2012-01-01 |

自创建客户 table 以来,已创建另一个 table 来保存客户信息

客户 2

| id |    name | year_joined | month_joined | day_joined |
|----|---------|-------------|--------------|------------|
|  4 |     Ken |        2013 |            1 |          1 |
|  5 | Lindsey |        2013 |            1 |          1 |
|  1 |     Bob |        2012 |            1 |          1 |

您会注意到,虽然 Customer2 包含前两个条目的新客户,但它也包含 Bob,他与第一个 table 中的鲍勃相同,并更新了信息以匹配新的 Customer2 table 布局。

我需要 select 基于 ID 列表将所有这些记录放入一个结果集中,假设 ID 是唯一的。因此我们可以确定 Customer 中的 Bob 与 Customer2 中的 Bob 相同。我目前正在用这样的联合声明来做这件事。

select * 
from (
select id, 
name, 
date_joined, 
'' as year_joined, 
'' as month_joined, 
'' as day_joined 
from customer 
union 
select id,
name,
'' as date_joined,
year_joined,
month_joined,
day_joined 
from customer2 ) 
as U where U.id in (list of ID's)

但是这会导致 table 看起来像这样

| id |    name | date_joined | year_joined | month_joined | day_joined |
|----|---------|-------------|-------------|--------------|------------|
|  4 |     Ken |             |        2013 |            1 |          1 |
|  5 | Lindsey |             |        2013 |            1 |          1 |
|  1 |     Bob |             |        2012 |            1 |          1 |
|  1 |     Bob |  2012-01-01 |             |              |            |
|  2 |    Jack |  2012-01-01 |             |              |            |
|  3 |    Jill |  2012-01-01 |             |              |            |

正如我们所见,我们有 Bob 的 'duplicate' 条记录,它们并不是真正的重复记录。我的问题是:当我遇到这样的 'duplicates' 时,有什么方法可以指定只从 Customer2 table 中选择记录吗?我需要这个,因为我不想重复,更愿意保留与最新 table 布局相匹配的记录。

您必须使数据完全匹配。像这样的东西可以工作:

select * 
from (
select id, 
name, 
datepart(year,date_joined) as year_joined, 
datepart(month,date_joined) as month_joined, 
datepart(day,date_joined) as day_joined 
from customer 
union 
select id,
name,
year_joined,
month_joined,
day_joined 
from customer2 ) 
as U where U.id in (list of ID's)

这应该让你开始:

SELECT
  id
  , name
  , date_joined
  , NULL year_joined
  , NULL month_joined
  , NULL day_joined
FROM Customer
WHERE id NOT IN (SELECT id FROM Customer2)
UNION ALL
SELECT
  id
  , name
  , NULL
  , year_joined
  , month_joined
  , day_joined
FROM Customer2
ORDER BY id
;

或者,仅使用 SET 操作:

(SELECT
  id
  , name
  , date_joined
  , NULL year_joined
  , NULL month_joined
  , NULL day_joined
FROM Customer
EXCEPT
  (SELECT
    id
    , name
    , CONVERT(DATE,
            CAST(year_joined AS VARCHAR(4)) + '-'
              + CAST(month_joined AS VARCHAR(2)) + '-'
              + CAST(day_joined AS VARCHAR(2))
            , 102
           )
    , NULL
    , NULL
    , NULL
  FROM Customer2
  )
)
UNION ALL
SELECT
  id
  , name
  , NULL
  , year_joined
  , month_joined
  , day_joined
FROM Customer2
ORDER BY id
;

要么从 Customer 中获取 notCustomer2 中找到的那些,然后合并它们与所有在 Customer2:

中找到的
| id |    name | date_joined | year_joined | month_joined | day_joined |
|----|---------|-------------|-------------|--------------|------------|
|  1 |     Bob |      (null) |        2012 |            1 |          1 |
|  2 |    Jack |  2012-01-01 |      (null) |       (null) |     (null) |
|  3 |    Jill |  2012-01-01 |      (null) |       (null) |     (null) |
|  4 |     Ken |      (null) |        2013 |            1 |          1 |
|  5 | Lindsey |      (null) |        2013 |            1 |          1 |

查看实际效果:SQL Fiddle

虽然我自己,我通常更喜欢真正的日期列而不是带有日期粒子的三列...

请评论,如果这需要调整/进一步的细节。