列多时如何旋转

时间:2019-09-12 20:19:12

标签: sql tsql pivot-table

我想我了解PIVOT的概念,但是在将此查询转换为PIVOT时遇到很多麻烦:

SELECT ID,
CASE WHEN [line] = "1" THEN code ELSE            "" AS one_CODE,
CASE WHEN [line] = "1" THEN name ELSE            "" AS one_NAME,
CASE WHEN [line] = "1" THEN address_line_1 ELSE  "" AS one_ADDRESS_LINE_1,
CASE WHEN [line] = "1" THEN address_line_2 ELSE  "" AS one_ADDRESS_LINE_2,
CASE WHEN [line] = "1" THEN address_city ELSE    "" AS one_ADDRESS_CITY,
CASE WHEN [line] = "1" THEN address_state ELSE   "" AS one_ADDRESS_STATE,
CASE WHEN [line] = "1" THEN address_zip ELSE     "" AS one_ADDRESS_ZIP,
CASE WHEN [line] = "2" THEN code ELSE            "" AS two_CODE,
CASE WHEN [line] = "2" THEN name ELSE            "" AS two_NAME,
CASE WHEN [line] = "2" THEN address_line_1 ELSE  "" AS two_ADDRESS_LINE_1,
CASE WHEN [line] = "2" THEN address_line_2 ELSE  "" AS two_ADDRESS_LINE_2,
CASE WHEN [line] = "2" THEN address_city ELSE    "" AS two_ADDRESS_CITY,
CASE WHEN [line] = "2" THEN address_state ELSE   "" AS two_ADDRESS_STATE,
CASE WHEN [line] = "2" THEN address_zip ELSE     "" AS two_ADDRESS_ZIP,
CASE WHEN [line] = "3" THEN code ELSE            "" AS three_CODE,
CASE WHEN [line] = "3" THEN name ELSE            "" AS three_NAME,
CASE WHEN [line] = "3" THEN address_line_1 ELSE  "" AS three_ADDRESS_LINE_1,
CASE WHEN [line] = "3" THEN address_line_2 ELSE  "" AS three_ADDRESS_LINE_2,
CASE WHEN [line] = "3" THEN address_city ELSE    "" AS three_ADDRESS_CITY,
CASE WHEN [line] = "3" THEN address_state ELSE   "" AS three_ADDRESS_STATE,
CASE WHEN [line] = "3" THEN address_zip ELSE     "" AS three_ADDRESS_ZIP
FROM MYTABLE

所需结果:

+----+----------+----------+--------------------+--------------------+------------------+-------------------+-----------------+------------+------------+--------------------+--------------------+------------------+-------------------+-----------------+---------------+------------+----------------------+----------------------+--------------------+---------------------+-------------------+
| ID | one_CODE | one_NAME | one_ADDRESS_LINE_1 | one_ADDRESS_LINE_2 | one_ADDRESS_CITY | one_ADDRESS_STATE | one_ADDRESS_ZIP |  two_CODE  |  two_NAME  | two_ADDRESS_LINE_1 | two_ADDRESS_LINE_2 | two_ADDRESS_CITY | two_ADDRESS_STATE | two_ADDRESS_ZIP |  three_CODE   | three_NAME | three_ADDRESS_LINE_1 | three_ADDRESS_LINE_2 | three_ADDRESS_CITY | three_ADDRESS_STATE | three_ADDRESS_ZIP |
+----+----------+----------+--------------------+--------------------+------------------+-------------------+-----------------+------------+------------+--------------------+--------------------+------------------+-------------------+-----------------+---------------+------------+----------------------+----------------------+--------------------+---------------------+-------------------+
|  1 | a        | b        | c                  | d                  |                  |                   |                 | bluecross  | blueshield |                    |                    |                  |                   |                 |               |            |                      |                      |                    |                     |                   |
|  2 | anthem   | myerland | 234                |                    |                  |                   |                 |            |            |                    |                    |                  |                   |                 |               |            |                      |                      |                    |                     |                   |
|  3 | anthem   | b        | 234 albin          |                    |                  |                   |                 | blueshield |            |                    |                    |                  |                   |                 | hartford life |            |                      |                      |                    |                     |                   |
+----+----------+----------+--------------------+--------------------+------------------+-------------------+-----------------+------------+------------+--------------------+--------------------+------------------+-------------------+-----------------+---------------+------------+----------------------+----------------------+--------------------+---------------------+-------------------+

如何为每个ID仅输出1条记录?

3 个答案:

答案 0 :(得分:2)

使用聚合:

select id,
       MAX(CASE WHEN [line] = 1 THEN code END) AS one_CODE,
       MAX(CASE WHEN [line] = 1 THEN name END) AS one_NAME,
       . . .
from t
group by id;

注意:

  • SQL Server使用双引号分隔标识符,而不是字符串。此查询不需要双引号。
  • 称为line的事物可能是数字,因此比较值应该是数字。
  • 这将返回NULL而不是空字符串。
  • 对于此查询尝试使用pivot,我认为没有好处。

答案 1 :(得分:1)

如果可以忍受性能,请查找CHOOSE函数。我已经在下面实现了。

    SELECT ID,
    MAX(CHOOSE([line],code)) AS one_CODE,
    MAX(CHOOSE([line],name)) AS one_name,
    MAX(CHOOSE([line],address_line_1)) AS one_address_[line]_1 ,
    MAX(CHOOSE([line],address_line_2)) AS one_address_[line]_2,
    MAX(CHOOSE([line],address_city)) AS one_address_city ,
    MAX(CHOOSE([line],address_state)) AS one_address_state,
    MAX(CHOOSE([line],address_zip)) AS one_address_zip ,
    MAX(CHOOSE([line]-1,code)) AS two_CODE,
    MAX(CHOOSE([line]-1,name)) AS two_name,
    MAX(CHOOSE([line]-1,address_line_1)) AS two_address_[line]_1 ,
    MAX(CHOOSE([line]-1,address_line_2)) AS two_address_[line]_2,
    MAX(CHOOSE([line]-1,address_city)) AS two_address_city,
    MAX(CHOOSE([line]-1,address_state)) AS two_address_state,
    MAX(CHOOSE([line]-1,address_zip)) AS two_address_zip,
    MAX(CHOOSE([line]-2,code)) AS three_CODE,
    MAX(CHOOSE([line]-2,name)) AS three_name,
    MAX(CHOOSE([line]-2,address_line_1)) AS three_address_[line]_1 ,
    MAX(CHOOSE([line]-2,address_line_2)) AS three_address_[line]_2,
    MAX(CHOOSE([line]-2,address_city)) AS three_address_city,
    MAX(CHOOSE([line]-2,address_state)) AS three_address_state,
    MAX(CHOOSE([line]-2,address_zip)) AS three_address_zip
    FROM MYTABLE
    GROUP BY ID;

答案 2 :(得分:1)

一个好的自我连接怎么样,在我深入答案之前,我只是先陈述一下我的假设,表中有7列,以及与行相关的键ID。如果是这种情况,您要做的就是

select a.ID
  , a.CODE as one_code
  , a.name as One_name
  , a.address_line_1 as one_address_line_1
  , a.ADDRESS_LINE_2 as one_ADDRESS_LINE_2
  , a.City as One_city
  , a.state as One_state
  , a.zip as one_zip
  , a.CODE as one_code
  , b.name as two_name
  , b.address_line_1 as two_address_line_1
  , b.ADDRESS_LINE_2 as two_ADDRESS_LINE_2
  , b.City as two_city
  , b.state as two_state
  , b.zip as two_zip
  , c.name as three_name
  , c.address_line_1 as three_address_line_1
  , c.ADDRESS_LINE_2 as three_ADDRESS_LINE_2
  , c.City as three_city
  , c.state as three_state
  , c.zip as three_zip
from mytable a
  left outer join mytable b on a.id = b.id and b.line = 2
  left outer join mytable c on c.id = a.id and c.line = 3
where a.line = 1

所以我们正在做的事情称为自连接,因为所有三组数据都在同一张表中,因此我们将具有不同行值的行作为单独的表进行别名,然后将其外部联接。我们使用左外部连接,因为它看起来只需要1行,而2和3行是可选的。希望这会有所帮助:)