连接两个表并将行作为列

时间:2015-06-19 01:24:40

标签: sql join

我有两张桌子。一个是用户ID的事务表,具有以下细节。

user_id Product_id timestamp transaction_id
123     A_1                   ID1
123     A_2                   ID1
124     A_1                   ID2 
125     A_2

现在有一个product_id映射与产品所属的部门

映射:

Product_id   Division
A_1          Grocery
A_2          Electronics and so on

我需要一个最终表格,其中我为每个用户ID创建一条记录,并将每个部门中购买的相应项目作为单独的列。喜欢

User_ID   Grocery  Electronics
123        1       1
124        1       0  

我做了类似的事情:

select user_id, case (when Division ="Grocery" then count(product_id) else 0) end as Grocery 
when Division="Electronics" then count(product_id) else 0) end as Electronics 
from 
( select user_id, a.product_id, b.division from transact as a
left join 
mapping b
on a.product_id=b.product_id
) 
group by user_id

Does this sound good?

3 个答案:

答案 0 :(得分:2)

使用条件聚合时,case是聚合函数的参数:

select user_id,
       sum(case when m.Division = 'Grocery' then 1 else 0 end) as Grocery, 
       sum(case when m.Division = 'Electronics' then 1 else 0 end) as Electronics 
from transact t left join 
     mapping m
     on t.product_id = m.product_id
group by user_id

SQL Fiddle

另外:

  • 您的表别名应该是表的缩写。使代码更易于理解。
  • 您不需要子查询。
  • 对字符串常量使用单引号。这是SQL标准。

答案 1 :(得分:0)

这是Gordon Linoff的回答的动态版本,它使用条件聚合。这适用于SQL-Server。

DECLARE @sql1 VARCHAR(4000) = ''
DECLARE @sql2 VARCHAR(4000) = ''
DECLARE @sql3 VARCHAR(4000) = ''

SELECT @sql1 = 
'SELECT
    t.user_id
'

SELECT @sql2 = @sql2 +
'   , SUM(CASE WHEN m.division = ''' + division + ''' THEN 1 ELSE 0 END) AS [' + division + ']' + CHAR(10)
FROM(
    SELECT DISTINCT division FROM Mapping
)t
ORDER BY division

SELECT @sql3 = 
'FROM Transact t
LEFT JOIN Mapping m
    ON m.product_id = t.product_id
GROUP BY t.user_id'

PRINT (@sql1 + @sql2 + @sql3)
EXEC (@sql1 + @sql2 + @sql3)

SQL Fiddle

答案 2 :(得分:0)

根据我的理解,它也可以使用PIVOT实现

declare @transact table (user_id int,product_id varchar(5),transaction_id varchar(5))
    insert into @transact (user_id,product_id,transaction_id)values (123,'A_1','ID1'),(123,'A_2','ID1'),(124,'A_1','ID2'),(125,'A_2',NULL)

    declare @mapping table (product_id varchar(5),division varchar(20))
    insert into @mapping (product_id,division)values ('A_1','Grocery'),('A_2','Electronics')

    select * from (
    select t.user_id,tt.division as Division,tt.product_id As product_id from @transact t
    left join @mapping tt
    on t.product_id = tt.product_id)T
    PIVOT(COUNT(product_id)FOR division IN ([Grocery],[Electronics]))P