连接两个表时如何在不同的行中显示数据

时间:2012-08-28 16:05:54

标签: tsql

我有2个温度。看起来像这样的表

@t1(p_ssn,p_fname,p_lname,Gender,.............) - >此表包含员工记录,并且包含 30列

@t2(p_ssn,benefit,medical_premium,dental_premium,..............) - >此表具有员工福利,并且大约有 60列

@t1中的每条记录都会在@t2

中包含一条或多条相应的记录

如何在表之间进行连接以获得这样的显示(在p_ssn上加入) 我想要每个员工记录,然后是所有福利记录 - 每个记录在不同的行上

p_fname,p_lname,Gender etc...      -> 1st employee
benefit1,medical_premium1,dental_premium_1     -> all the benefit records for this employee
p_fname,p_lname,Gender etc...      -> 2nd  employee
benefit1,medical_premium1,dental_premium_1 

现在,我正在使用循环。但是由于每个记录的大小,它只是在中途停止后挂起。


@Tim - 这就是我被困的地方。 @ t1只有30列,但@ t2有60列

- 实际查询

    select col1, col2 from 
(     -- Get employees     
 select 10 as ordinal, p_ssn, p_fname as col1, p_lname as col2,**there are only 30 columns here**     
 from @t1     
union all    
 -- Get benefits     
select 20 as ordinal, a.p_ssn, cast(b.benefit as varchar(50)), cast(b.premium as varchar(50)) ,**I want to display more columns here like b.col1,b.col2,b.col3 etc...60 columns**    
from @t1 a         
 join @t2 b on a.p_ssn = b.p_ssn ) as a order by p_ssn, ordinal 

我知道我可以做以下事情

  select 10 as ordinal, p_ssn, p_fname as col1, p_lname as col2,'','',''
from @t1
 union all
select 20 as ordinal, a.p_ssn, cast(b.benefit as varchar(50)), cast(b.premium as varchar(50)),b.col1,b.col2,n.col3

但这是一个文件提要,不允许空白。事实上,我无法使用强制转换,因为长度和数据类型已定义且无法更改

2 个答案:

答案 0 :(得分:0)

你最终可能会做这样的事情:

-- Setup demo data
declare @t1 table (
      p_ssn char(11) not null primary key
    , p_fname varchar(50) not null
    , p_lname varchar(50) not null
)
insert into @t1 select '000-00-0000', 'Joe', 'Blow'
insert into @t1 select '111-11-1111', 'Jane', 'Doe'
declare @t2 table (
      p_ssn char(11) not null
    , benefit varchar(50)
    , premium int
)
insert into @t2 select '000-00-0000', 'Benefit 1', 100
insert into @t2 select '000-00-0000', 'Benefit 2', 200
insert into @t2 select '111-11-1111', 'Benefit 1', 300
insert into @t2 select '111-11-1111', 'Benefit 2', 400

-- Actual query
select col1, col2
from (
    -- Get employees
    select 10 as ordinal, p_ssn, p_fname as col1, p_lname as col2
    from @t1
    union all
    -- Get benefits
    select 20 as ordinal, a.p_ssn, cast(b.benefit as varchar(50)), cast(b.premium as varchar(50))
    from @t1 a
        join @t2 b on a.p_ssn = b.p_ssn
) as a
order by p_ssn, ordinal

获得这样的输出:

col1        col2
Joe         Blow
Benefit 1   100
Benefit 2   200
Jane        Doe
Benefit 1   300
Benefit 2   400

诀窍是生成我们可以在以后排序的ordinal列。

我通常建议不要在数据库引擎中创建这样的报告,因为这就是您的网络/应用服务器上的报告工具和前端代码的用途(这些通常会更好地扩展)。另外,请注意使用SSN as a primary key

答案 1 :(得分:0)

我的假设是你的输出是连接字段(例如p_lname +','+ p_fname)。这可能是一个可能的解决方案:

declare @tmpResult table(GroupRankNo int
                        , Name nvarchar(100)
                        , Benefits nvarchar(500)
                        , SSN int)

insert into @tmpResult table(GroupRankNo
                            , Name
                            , Benefits
                            , SSN)
select row_number() over(partition by aa.Name order by aa.Name) as GroupRankNo
        , aa.Name
        , aa.Benefits
        , aa.p_ssn
from
(       
    select a.p_fname + ', ' + a.p_lname as Name
            , b.benefit + ', ' + b.premium as Benefits
            , a.p_ssn
    from @t1 a
    inner join @t2 b on b.p_ssn = a.p_ssn
) aa                                


select aa.ColumnData
from
(
    select SSN
            , Name as ColumnData
            , 0 as RowType --Header
    from @tmpResult
    where GroupRankNo = 1

    union

    select SSN
            , Benefits as ColumnData
            , 1 as RowType --Detail
    from @tmpResult
) aa
order by aa.SSN
            , RowType asc

我还没有测试过。但你会得到这个想法,使用“row_number()over partition by”