将列旋转到连接表的行

时间:2015-06-14 14:50:40

标签: sql sql-server join pivot

我有两个类似于下面所示的表格(为简单起见,省略了字段)。

lead

 id  |  fname    |   lname    |     email
 ---------------------------------------------
 1   |  John     |   Doe      |    jd@test.com
 2   |  Mike     |   Johnson  |    mj@test.com

leadcustom

 id   |   leadid     |    name         |    value
 -------------------------------------------------
 1    |   1          |    utm_medium   |    cpc
 2    |   1          |    utm_term     |    fall
 3    |   1          |    subject      |    business
 4    |   2          |    utm_medium   |    display
 5    |   2          |    utm_term     |    summer
 6    |   2          |    month        |    may
 7    |   2          |    color        |    red

我有一个数据库,可以捕获各种表单的潜在客户,这些表单通常包含许多不同的表单字段。第一个表获取我知道的每个表单上的基本信息。第二个表捕获已发送的所有其他表单字段,因此它实际上可以包含许多不同的字段。

我要做的是进行联接,我可以从lead表中获取所有字段以及utm_medium表中的utm_termleadcustom。即使他们被发送,我也不需要任何其他字段。

期望的结果:

 id    |  fname    |    lname   |   email       |  utm_medium   |  utm_term
 ---------------------------------------------------------------------------
 1     |  John     |    Doe     |   jd@test.com |  cpc          |  fall
 2     |  Mike     |    Johnson |   mj@test.com |  display      |  summer

我知道我能做到这一点的唯一方法就是获取所有潜在客户数据,然后为每条记录拨打更多电话来获取我正在寻找的leadcustom数据,但我知道有更高效的获取方式这个数据。

我感谢任何帮助,我不能改变我捕获数据和表格式的方式。

5 个答案:

答案 0 :(得分:3)

如果您的列已修复,则可以使用group by + case + max执行此操作,如下所示:

select
  fname,
  lname,
  email,
  max(case when name = 'utm_medium' then value end) as utm_medium,
  max(case when name = 'utm_term' then value end) as utm_term
from
  lead l
  join leadcustom c
    on l.id = c.leadid
group by
  fname,
  lname,
  email

该情况将在与给定名称匹配时从leadcustom表中指定值,否则它将返回null,如果存在于null上,则max将选择获取的指定值。

您可以在SQL Fiddle

中对此进行测试

另一种方法是使用pivot运算符,但语法稍微复杂一点 - 或者至少对我来说这更容易。

答案 1 :(得分:0)

您可以尝试使用pivotjoin

select [id]
     , [fname]
     , [lname]
     , [email]
     , [utm_medium]
     , [utm_term]
from ( select t2.*
            , t1.[name]
            , t1.[value]
       from [leadcustom] t1
       join [lead] t2 on t2.[id] = t1.[leadid]
) t
pivot (
       max([value])
       for [name] in ([utm_medium], [utm_term])
) pt

pivot通过将表达式中[value]列的唯一值转换为[utm_medium][utm_term]来旋转已连接的表值表达式输出中的列,并使用max函数执行伪聚合(它的工作原理是因为相应的列可以为一个唯一的透视列提供多个值,在本例中为[name] [value] }})

SQLFiddle

答案 2 :(得分:0)

您可以使用cte或派生表来解决此问题:

CTE:

;with cte as 
(
    select leadid, [name], [value]
    from leadcustom
    where name in('utm_medium', 'display')
)

select id, fname, lname, email, [name], [value]
from lead 
inner join cte on(id = leadid)

派生表:

select id, fname, lname, email, [name], [value]
from lead 
inner join
(
    select leadid, [name], [value]
    from leadcustom
    where name in('utm_medium', 'display')
) derived on(id = leadid)

因为苏斯洛夫使用了JamesZ的小提琴,I will use it too ......

答案 3 :(得分:0)

除非我错误地解释你的问题 - 在这种情况下我很乐意纠正 - 你可以通过一个简单的左连接来实现你的目标,你加入第一个表的ID:

Imports System.IO

Public Class frmEmployee
Sub frmEmployee_load(ByVal sender As Object, e As System.EventArgs)
    Dim strFileName = InputBox("Please name the file you would like to save the data to: ")

End Sub
Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click
    txtEmail.Clear()
    txtExtension.Clear()
    txtFirst.Clear()
    txtLast.Clear()
    txtMiddle.Clear()
    txtNumber.Clear()
    txtPhone.Clear()

End Sub

Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click

Dim inputFile As New StreamWriter(strFileName)

    If File.Exists(strFileName) = True Then
        inputFile = File.CreateText(strFileName)
        inputFile.Write(txtEmail.Text)
        inputFile.Write(txtExtension.Text)
        inputFile.Write(txtFirst.Text)
        inputFile.Write(txtLast.Text)
        inputFile.Write(txtMiddle.Text)
        inputFile.Write(txtNumber.Text)
        inputFile.Write(txtPhone.Text)
        inputFile.Write(cmbDepart.Text)
    Else
        MessageBox.Show("" & strFileName & "Cannot be created or found.")
    End If
End Sub

Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
    Me.Close()
End Sub

答案 4 :(得分:0)

declare @t table (Id int,fname varchar(10),lname varchar(10),email varchar(20))
insert into @t(Id,fname,lname,email)values (1,'john','doe','jd@test.com'),(2,'mike','johnson','mj@test.com')
declare @tt table (id int,leadid int,name varchar(10),value varchar(10))
insert into @tt(id,leadid,name,value)values
(1,1,'utm_medium','cpc'),
(2,1,'utm_term','fall'),
(3,1,'subject','business'),
(4,2,'utm_medium','display'),
(5,2,'utm_term','summer'),
(6,2,'month','may'),(7,2,'color','red')
select Id,fname,lname,
email,
[utm_medium],
[utm_term] 
from (
select t.Id,
t.fname,
t.lname,
t.email,
tt.name,
tt.value
   from @t t JOIN @tt tt
   ON t.Id = tt.leadid)R
PIVOT(MAX(value) for name IN([utm_medium],[utm_term]))P
相关问题