SQL多次显示相同的列

时间:2012-12-07 19:50:25

标签: mysql pivot

表1中有NameId,年龄,性别......
表2有版本号,TimeStamp ...

现在我想从表1中选择NameId,从表2中多次选择版本号和时间戳,我需要查询table2中的所有版本和时间记录, 任何人都可以给我一些关于如何查询的想法吗?

NameId  |   Version/Time        |   Version/Time    |   Version/Time …

Angela  |    1  /  01.01.2010   |   2 / 01.02.2010  |   3 / 01.03.2010
Betty   |    1  /  01.01.2010   |   2 / 01.02.2010  |   3 / 01.03.2010
Cathy   |    1  /  01.01.2010   |   2 / 01.02.2010  |   3 / 01.03.2010
...     |   ....                |                   |   

2 个答案:

答案 0 :(得分:0)

如果正如你所说的那样,任何固定值集都不起作用,那么你需要动态的sql来完成你的工作。

这些内容:

CREATE PROCEDURE [dbo].[usp_pivot_]
AS

DECLARE @columns VARCHAR(1000)

SELECT @columns = COALESCE(@columns + ',[' + cast(versionTime as varchar) + ']',
'[' + cast(versionTime as varchar)+ ']')
FROM table1 inner join table2 on table1.NameId = table2.NameId
GROUP BY versionTime 

DECLARE @query VARCHAR(8000)

SET @query = '
SELECT *
FROM table1 inner join table2 on table1.NameId = table2.NameId
PIVOT
(
first(versionTime)
FOR [versionTime]
IN (' + @columns + ')
)
AS p'

EXECUTE(@query)

答案 1 :(得分:0)

通常的方法是在两个表之间执行JOIN,例如

SELECT t1.NameId
     , t2.VersionNo
     , t2.Timestamp
  FROM table_one t1
  LEFT
  JOIN table_two t2
    ON t2.NameId = t1.NameId
 ORDER
    BY t1.NameId
     , t2.VersionNo

这将为您提供如下结果:

NameId   VersionNo TimeStamp
-------- --------- ----------
Angela   1         01.01.2010   
Angela   2         01.02.2010  
Angela   3         01.03.2010
Betty    1         01.01.2010   
Betty    2         01.02.2010  
Betty    3         01.03.2010
Cathy    1         01.01.2010   
Cathy    2         01.02.2010  
Cathy    3         01.03.2010

(这假设table_twotable_one的NameId值相关。原始问题中提供的示例数据可能会使table_two中的三行与之匹配table_one中的每一行(即笛卡尔积)。在这种情况下,它将是声明中的CROSS JOIN:

SELECT t1.NameId
     , t2.VersionNo
     , t2.Timestamp
  FROM table_one t1
 CROSS
  JOIN table_two t2
 ORDER
    BY t1.NameId
     , t2.VersionNo

要将该查询的结果集转换为“交叉表”(或数据透视表),并在同一行输出中显示每个单独的table_two行,通常在客户端中更好地处理,而不是而不是在SQL语句中。

但是,MySQL可以返回一个类似的结果集,每个VersionNo和Timestamp值都在一个单独的列中;但要做到这一点的查询并非易事。

(一个简单的替代方法是使用GROUP_CONCAT聚合函数,但返回单个列,而不是单独的列,并受max_allowd_packet_size限制。)

SELECT t1.NameID
     , GROUP_CONCAT(CONCAT(t2.VersionNo,'/',t2.Timestamp) ORDER BY t2.VersionNo)
  FROM table_one t1
  LEFT
  JOIN table_two t2
    ON t2.NameId = t1.NameId
 GROUP
    BY t1.NameId
 ORDER
    BY t1.NameId

再次假设table_twotable_one相关,一种相当笨拙但易于理解的方法是在查询的SELECT列表中使用相关子查询,例如

SELECT t1.NameId
     , ( SELECT CONCAT(t2a.VersionNo,' / ',t2a.Timestamp)
           FROM table_two t2a WHERE t2a.NameId = t1.NameID
          ORDER BY t2a.VersionNo LIMIT 0,1 
       ) AS `Version/Time`
     , ( SELECT CONCAT(t2b.VersionNo,' / ',t2b.Timestamp)
           FROM table_two t2b WHERE t2b.NameId = t1.NameID
          ORDER BY t2b.VersionNo LIMIT 1,1 
       ) AS `Version/Time`
     , ( SELECT CONCAT(t2c.VersionNo,' / ',t2c.Timestamp)
           FROM table_two t2c WHERE t2c.NameId = t1.NameID
          ORDER BY t2c.VersionNo LIMIT 2,1
       ) AS `Version/Time`
  FROM table_one t1
 ORDER BY t1.NameId

该查询将返回类似于原始问题中显示的结果集,尽管返回的列数是在SELECT语句中静态定义的。