【问题标题】:MERGE to target columns using source rows?使用源行合并到目标列?
【发布时间】:2011-05-19 04:55:30
【问题描述】:

我有一些结构良好的数据,如下所示:

CREATE TABLE SourceBodyPartColors
(
 person_ID INTEGER NOT NULL, 
 body_part_name VARCHAR(5) NOT NULL
    CHECK (body_part_name IN ('hair', 'eye', 'teeth')), 
 color VARCHAR(20) NOT NULL, 
 UNIQUE (color, body_part_name, person_ID)
);

INSERT INTO SourceBodyPartColors (person_ID, body_part_name, color)
   VALUES (1, 'eye', 'blue'), 
          (1, 'hair', 'blond'), 
          (1, 'teeth', 'white'), 
          (2, 'hair', 'white'), 
          (2, 'teeth', 'yellow'), 
          (3, 'hair', 'red');

遗憾的是,目标结构并没有那么好,看起来更像这样:

CREATE TABLE TargetBodyPartColors
(
 person_ID INTEGER NOT NULL UNIQUE, 
 eye_color VARCHAR(20), 
 hair_color VARCHAR(20), 
 teeth_color VARCHAR(20)
);

INSERT INTO TargetBodyPartColors (person_ID)
   VALUES (1), (2), (3);

我可以像这样写一个 SQL-92 UPDATE

UPDATE TargetBodyPartColors
   SET eye_color = (
                    SELECT S1.color
                      FROM SourceBodyPartColors AS S1
                     WHERE S1.person_ID 
                              = TargetBodyPartColors.person_ID
                           AND S1.body_part_name = 'eye'
                   ), 
       hair_color = (
                     SELECT S1.color
                       FROM SourceBodyPartColors AS S1
                      WHERE S1.person_ID 
                               = TargetBodyPartColors.person_ID
                            AND S1.body_part_name = 'hair'
                    ), 
       teeth_color = (
                      SELECT S1.color
                        FROM SourceBodyPartColors AS S1
                       WHERE S1.person_ID 
                                = TargetBodyPartColors.person_ID
                             AND S1.body_part_name = 'teeth'
                     );

...但是重复的代码困扰着我。

我认为使用MERGE 进行简化是一个很好的候选人,但我想不出任何合理的东西。

任何想法如何使用MERGE 处理此数据。 (注意:我想避免专有的UPDATE..FROM syntax,谢谢。)

【问题讨论】:

  • AFAIK,MERGE 是 SQL:2003,真的更好吗?
  • @marc_s:我明白为什么您可能认为它是 EAV,但实际上并非如此。请参阅有关第一范式 (en.wikipedia.org/wiki/First_normal_form) 的 Wikipedia 文章:“目标”结构类似于子标题“跨列重复组”下显示的 Customer 表(即违反 1NF)。 “源”结构更像是在“符合 1NF 的设计”子标题下显示的Customer Telephone Table 表。
  • @onedaywhen - 我不同意这一点。我违反 1NF 的经验法则是,您可以交换列值并最终得到语义相同的东西。如果您可以交换tel1tel2 并且语义不变,那么这显然不在1NF 中。参考文献Facts and Fallacies about First Normal Form
  • @Martin:您对 1NF 有自己的个人定义?!嗯,嗯,......我想这一定会让你感到安慰:)
  • @Martin:说真的。我认识到我快速起草的数据存在缺陷,例如“发色”和“眼色”不是同一个领域……谁有金色的眼睛?! :)

标签: sql tsql sql-server-2008 merge standards-compliance


【解决方案1】:
WITH Pivoted AS
(
  SELECT person_ID, eye, hair, teeth
  FROM SourceBodyPartColors
    PIVOT
    (
    MAX (color) FOR body_part_name IN ( [eye], [hair], [teeth] )
    ) AS pvt
  )  
MERGE TargetBodyPartColors AS target
USING  Pivoted AS source
ON (target.person_ID = source.person_ID)
WHEN MATCHED THEN 
UPDATE SET eye_color = source.eye,  
           hair_color = source.hair,  
           teeth_color = source.teeth ;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多