【问题标题】:Join table rows as column values sql将表行连接为列值 sql
【发布时间】:2017-11-08 15:42:56
【问题描述】:

在这种情况下,我有两个已加入的表,并且由于每个医生都可以拥有多个许可证,它会创建多个重复项。我想将多个许可证状态和编号添加到表 1 中,如下所示。

这需要动态完成,因为它可能是分配给一位医生的大量许可证。

表 1 如下所示。

assignid  physician_name  profession 
-------------------------------
    1        bob          md        
    2        travis       do        
    3        ryan         md        
    4        pete         pa        
    5        susan        np         
    6        ashley       cnp     

表2

assignid  license_state license_num
-------------------------------
     1       oh        561
     2       mi        987
     3       ca        785
     4       ny        965
     4       mi        125
     5       oh        369
     5       ca        541

加入

assignid  physician_name  profession license_state license_num
----------------------------------------------------------------
    1        bob          md             oh           561
    2        travis       do             mi           987
    3        ryan         md             ca           785
    4        pete         pa             ny           965
    4        pete         pa             mi           125
    5        susan        np             oh           369
    5        susan        np             ca           541

我想动态地将连接表更改为如下所示。

assignid  physician_name  profession license_state1 license_num1 license_state2 license_num2
--------------------------------------------------------------------------------------------------
   1        bob          md             oh           561
   2        travis       do             mi           987
   3        ryan         md             ca           785
   4        pete         pa             ny           965             mi       125
   5        susan        np             oh           369             ca       541

我尝试了这条路线,但这给了我作为列标题的状态。

WITH pivotdata AS (
SELECT assignid,physician_name, profession, license_state,license_num
FROM dbo.Physicians p JOIN dbo.Licenses l ON p.AssignID = l.AssignID
)

SELECT *
FROM
   pivotdata
   PIVOT (MAX(license_num) FOR license_state IN ([oh], [mi], [ca],[ny])) TT;

结果

physician_name  profession   oh  mi  ca  ny
-------------------------------------------
    bob          md          561
    travis       do             987
    ryan         md                  785
    pete         pa             125     965
    susan        np          369     541

【问题讨论】:

  • 好的,那么您尝试解决什么问题?
  • @Sami 我已经编辑了我的问题以显示我认为可行的方法。

标签: sql sql-server join pivot pivot-table


【解决方案1】:

您可以使用动态交叉表来解决此问题。我从 Jeff Moden 和他的文章这里学到了这项技术。 http://www.sqlservercentral.com/articles/Crosstab/65048/

if OBJECT_ID('tempdb..#Physicians') is not null
    drop table #Physicians

create table #Physicians
(
    AssignID int
    , PhysicianName varchar(20)
    , Profession varchar(10)
)

insert #Physicians values
(1, 'bob', 'md')
, (2, 'travis', 'do')
, (3, 'ryan', 'md')
, (4, 'pete', 'pa')
, (5, 'susan', 'np')
, (6, 'ashley', 'cnp')

if OBJECT_ID('tempdb..#Licenses') is not null
    drop table #Licenses

create table #Licenses
(
    AssignID int
    , LicenseState char(2)
    , LicenseNum int
)

insert #Licenses values
(1, 'oh', 561)
, (2, 'mi', 987)
, (3, 'ca', 785)
, (4, 'ny', 965)
, (4, 'mi', 125)
, (5, 'oh', 369)
, (5, 'ca', 541)

declare @StaticPortion nvarchar(2000) = 
    'with OrderedResults as
    (
        SELECT p.AssignID
            , p.PhysicianName
            , p.Profession
            , l.LicenseState
            , l.LicenseNum
            , ROW_NUMBER() over(partition by p.AssignID order by l.LicenseState) as RowNum
        FROM #Physicians p 
        JOIN #Licenses l ON p.AssignID = l.AssignID
    )
    select AssignID';

declare @DynamicPortion nvarchar(max) = '';
declare @FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by AssignID order by AssignID';

--the following cte is a tally table (another trick I learned from Jeff Moden)
with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
cteTally(N) AS 
(
    SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E2
)

select @DynamicPortion = @DynamicPortion + 
    ', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then LicenseState end) as LicenseState' + CAST(N as varchar(6)) + CHAR(10)
    + ', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then LicenseNum end) as LicenseNum' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <= 
(
    select top 1 Count(p.AssignID)
    FROM #Physicians p 
    JOIN #Licenses l ON p.AssignID = l.AssignID
    group by p.AssignID
    order by COUNT(*) desc
)


declare @SqlToExecute nvarchar(max) = @StaticPortion + @DynamicPortion + @FinalStaticPortion;

--you can comment the following. it is here for now so you can view the dynamic sql before it executes
select @SqlToExecute

--Once you are satisfied that the dynamic sql generated is correct simply uncomment the below line
--exec sp_executesql @SqlToExecute

【讨论】:

  • 非常感谢。这正是我想要做的! @SeanLange
  • 如果可行,您应该考虑将其标记为答案。但更重要的是,你了解里面发生了什么吗?
猜你喜欢
  • 1970-01-01
  • 2014-06-16
  • 2012-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-24
相关资源
最近更新 更多