将连接表的列旋转为行
Rotate columns to rows for joined tables
我有两个类似于下图的 table(为简单起见,省略了字段)。
Table lead
:
id | fname | lname | email
---------------------------------------------
1 | John | Doe | jd@test.com
2 | Mike | Johnson | mj@test.com
Table 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
我有一个数据库可以捕获各种表单的潜在客户,这些表单通常有许多不同的表单字段。第一个 table 获取我所知道的每个表格上的基本信息。第二个 table 捕获发送过来的所有其他表单字段,因此它实际上可以包含很多不同的字段。
我想做的是做一个连接,我可以从 lead
table 中获取所有字段以及 utm_medium
和 utm_term
来自 [=14] =] table。我不需要任何额外的字段,即使它们已发送过来。
想要的结果:
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
数据,但我知道我必须有一种更有效的方法获取此数据。
我很感激任何帮助,这不是我可以改变我捕获数据的方式和 table 格式的东西。
如果你的列是固定的,你可以像这样用 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 table 赋值,否则它将 return 为 null,如果它存在于 null 之上,max 将选择分配的值。
您可以在 SQL Fiddle
中进行测试
另一种方法是使用数据透视运算符,但该语法稍微复杂一些——或者至少这对我来说更容易。
你可以试试 pivot
和 join
:
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]
列的 unique 值转换为 [utm_medium]
和 [utm_term]
列在输出中,并使用 max
函数执行假聚合( 它之所以有效,是因为相应的列对于一个唯一的旋转列可以有多个值,在此案例,[name]
for [value]
).
您可以使用 cte
或派生的 table 来解决这个问题:
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)
派生 table:
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)
并且由于 suslov 使用了 JamesZ 的 fiddle,I will use it too...
除非我错误地解释了你的问题——在这种情况下,我很乐意得到纠正——你可以通过一个简单的左连接来实现你的目标,你可以在第一个 table:[=11 的 ID 上连接=]
select ld.*, ldcust.utm_medium, ldcust.utm_term
from lead ld
left join leadcustom ldcust
on ld.id = ldcust.leadid
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
我有两个类似于下图的 table(为简单起见,省略了字段)。
Table lead
:
id | fname | lname | email
---------------------------------------------
1 | John | Doe | jd@test.com
2 | Mike | Johnson | mj@test.com
Table 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
我有一个数据库可以捕获各种表单的潜在客户,这些表单通常有许多不同的表单字段。第一个 table 获取我所知道的每个表格上的基本信息。第二个 table 捕获发送过来的所有其他表单字段,因此它实际上可以包含很多不同的字段。
我想做的是做一个连接,我可以从 lead
table 中获取所有字段以及 utm_medium
和 utm_term
来自 [=14] =] table。我不需要任何额外的字段,即使它们已发送过来。
想要的结果:
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
数据,但我知道我必须有一种更有效的方法获取此数据。
我很感激任何帮助,这不是我可以改变我捕获数据的方式和 table 格式的东西。
如果你的列是固定的,你可以像这样用 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 table 赋值,否则它将 return 为 null,如果它存在于 null 之上,max 将选择分配的值。
您可以在 SQL Fiddle
中进行测试另一种方法是使用数据透视运算符,但该语法稍微复杂一些——或者至少这对我来说更容易。
你可以试试 pivot
和 join
:
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]
列的 unique 值转换为 [utm_medium]
和 [utm_term]
列在输出中,并使用 max
函数执行假聚合( 它之所以有效,是因为相应的列对于一个唯一的旋转列可以有多个值,在此案例,[name]
for [value]
).
您可以使用 cte
或派生的 table 来解决这个问题:
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)
派生 table:
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)
并且由于 suslov 使用了 JamesZ 的 fiddle,I will use it too...
除非我错误地解释了你的问题——在这种情况下,我很乐意得到纠正——你可以通过一个简单的左连接来实现你的目标,你可以在第一个 table:[=11 的 ID 上连接=]
select ld.*, ldcust.utm_medium, ldcust.utm_term
from lead ld
left join leadcustom ldcust
on ld.id = ldcust.leadid
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