如何获得UNION尊重列别名?

时间:2019-01-27 16:54:28

标签: sql sql-server tsql

很抱歉,标题不好,我想不出更好的办法。随时编辑。

我必须使用一个数据库表,该数据库表使用一列来存储不同类型的信息(如果是个人,则为姓,如果是公司,则为公司名)。我知道是一场噩梦,但事实就是如此。

为区分含义,还有另一列带有整数,该整数指定名称列中内容的类型。

此表的架构如下(简化):

ID int
dtype int
name varchar(50)

因此,示例可能如下所示:

ID       dtype       name
---------------------------
1        0           Smith
2        0           Trump
3        1           ABC Ltd.
4        1           XYZ Ltd.

我正在尝试使用以下T-SQL代码对此进行标准化:

WITH companies AS 
 (
  SELECT ID, name AS company 
  FROM nametable WHERE dtype=1
  ),
      people AS 
  (
  SELECT ID, name AS person 
  FROM nametable WHERE dtype=0
  ),
  SELECT * FROM companies UNION ALL SELECT * FROM people;

我希望得到的是一个带有模式的新表:

ID
dtype
company
person

或者,在表格视图中:

ID       dtype       person        company
------------------------------------------
1        0           Smith
2        0           Trump
3        1                         ABC Ltd.
4        1                         XYZ Ltd.

相反,该字段现在仅称为person,而不是name,但它仍然只是两种信息类型的一个字段。

我知道我可以创建一个新表并将每个部分结果插入其中,但是似乎应该有一个更简单的方法。任何建议表示赞赏。

2 个答案:

答案 0 :(得分:2)

您根本不需要使用UNION。更好的方法是使用一些聚合。

SELECT ID,
       MAX(CASE WHEN dtype = 0 THEN [name] END) AS company
       MAX(CASE WHEN dtype = 1 THEN [name] END) AS person 
FROM nametable
GROUP BY ID;  

UNION (ALL)并不“关心”别名。它将接收到的数据集合并为1。所有数据集必须具有相同的定义,返回的数据集将具有相同的定义。如果数据集的列别名不同,则将使用第一个数据集中提供的别名。 UNION不会检测到数据集的列名称不同,因此将不同的名称作为不同的列返回;这不是UNION所做的。

Edit:好吧,这将为OP提供所需的数据,但是,不需要聚合。老实说,我希望ID可以作为共享资源。因为那是通常,这是您唯一拥有此类可怕表格的时间。它不仅使该表更加混乱……

答案 1 :(得分:2)

看来您需要帮助的情况下

   select ID, dtype,case when dtype=0 then name end AS company,
   case when dtype=1 then name end  AS person
   FROM nametable 

CASE语句遍历条件,并在条件满足时返回一个值,从您的示例输入和输出中清除您要创建类型明智的新列,因此我使用了case语句