根据条件 sql 将行转为列
Transposing rows into columns based on a condition sql
我有以下 table(一个简化的例子,实际上 table 包含多个 ID,日期数量可变,每个日期的事件数量可变):
IDs Date Event
102 1996-10-16 00:00:00 A
102 1996-10-23 00:00:00 A
102 1996-10-23 00:00:00 B
102 1997-01-14 00:00:00 A
103 1997-01-14 00:00:00 D
103 1997-01-15 00:00:00 A
103 1997-01-16 00:00:00 A
103 1997-01-16 00:00:00 B
103 1997-01-16 00:00:00 C
我正在尝试获得一个 table,其中我将有不同的 IDs/Date 对,其中有多个事件重新编码的行被转置到列中。所以,我正在寻找一个 table,在这个例子中它看起来像这样:
IDs Date Event Event2 Event3
102 1996-10-16 00:00:00 A NULL NULL
102 1996-10-23 00:00:00 A B NULL
102 1997-01-14 00:00:00 A NULL NULL
103 1997-01-14 00:00:00 D NULL NULL
103 1997-01-15 00:00:00 A NULL NULL
103 1997-01-16 00:00:00 A B C
很抱歉没有发布任何代码,但坦率地说,我什至不知道如何开始。
如果您只有两个事件,您可以使用 min()
、max()
和一些额外的逻辑:
select ids, date, min(event) as event,
(case when min(event) <> max(event) then max(event) end) as event2
from table t
group by ids, date;
这是标准的 SQL,因此它应该适用于任何数据库。
先尝试这个 select ID,然后根据上面的 ID 获取所有列....
<?php
$query = $database->getRows("SELECT DISTINCT ids FROM table");
?>
<table>
<?php foreach($query as $row){ ?>
<tr>
<td><?php echo $row['ids']; ?></td>
<?php
$id= $row["ids"];
$sub_inner = $database->getRows("SELECT date,Event,Event2 FROM table where ids= :ids",
array(':ids'=>$id));
?>
<td><?php foreach($sub_inner as $list){ ?><?php echo $list['date']; ?></td><td><?php echo $list['Event']; ?><?php } ?></td>
<td><?php echo $list['Event2']; ?></td>
<?php } ?>
关于 PIVOT 方法的详细信息。
有用的答案:
Using PIVOT in SQL Server 2008
MSSQL dynamic pivot column values to column header
试试这个代码:
-- Temporary table...
create table ##myTable (
IDs int
,[Date] datetime
,[Event] varchar(1)
)
-- ... with sample data
insert ##myTable
select 102, '2010-01-01', 'A'
union select 102, '2010-01-01', 'B'
union select 102, '2010-01-01', 'C'
union select 102, '2010-01-01', 'E'
union select 103, '2010-01-01', 'A'
union select 104, '2010-01-01', 'B'
union select 104, '2010-01-01', 'C'
union select 105, '2010-01-01', 'F'
-- Variables
DECLARE @cols AS NVARCHAR(MAX)
,@query AS NVARCHAR(MAX)
-- Build column name for our result.
-- The ROW_NUMBER() operator gives us the rank of the event for
-- the combination of IDs and Date. With that, event B for IDs 104
-- will have rank 1, and then will appear in the 1st column.
SELECT @cols = STUFF(
(SELECT DISTINCT
',' + QUOTENAME('Event' + LTRIM(STR(
ROW_NUMBER() OVER (
PARTITION BY IDs, [Date]
ORDER BY IDs, [Date]
)
)))
FROM ##myTable
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
, 1, 1, '')
set @query = '
SELECT IDs, [Date], ' + @cols + '
FROM (
SELECT IDs
,[Date]
,[Event]
,''Event'' + LTRIM(STR(
ROW_NUMBER() OVER (
PARTITION BY IDs, [Date]
ORDER BY IDs, [Date]
)
)) as [EventNo]
FROM ##myTable
) x
PIVOT
(
MAX([Event])
FOR [EventNo] IN (' + @cols + ')
) p'
execute sp_executesql @query
-- Remove temporary table
drop table ##myTable
结果:
我有以下 table(一个简化的例子,实际上 table 包含多个 ID,日期数量可变,每个日期的事件数量可变):
IDs Date Event
102 1996-10-16 00:00:00 A
102 1996-10-23 00:00:00 A
102 1996-10-23 00:00:00 B
102 1997-01-14 00:00:00 A
103 1997-01-14 00:00:00 D
103 1997-01-15 00:00:00 A
103 1997-01-16 00:00:00 A
103 1997-01-16 00:00:00 B
103 1997-01-16 00:00:00 C
我正在尝试获得一个 table,其中我将有不同的 IDs/Date 对,其中有多个事件重新编码的行被转置到列中。所以,我正在寻找一个 table,在这个例子中它看起来像这样:
IDs Date Event Event2 Event3
102 1996-10-16 00:00:00 A NULL NULL
102 1996-10-23 00:00:00 A B NULL
102 1997-01-14 00:00:00 A NULL NULL
103 1997-01-14 00:00:00 D NULL NULL
103 1997-01-15 00:00:00 A NULL NULL
103 1997-01-16 00:00:00 A B C
很抱歉没有发布任何代码,但坦率地说,我什至不知道如何开始。
如果您只有两个事件,您可以使用 min()
、max()
和一些额外的逻辑:
select ids, date, min(event) as event,
(case when min(event) <> max(event) then max(event) end) as event2
from table t
group by ids, date;
这是标准的 SQL,因此它应该适用于任何数据库。
先尝试这个 select ID,然后根据上面的 ID 获取所有列....
<?php
$query = $database->getRows("SELECT DISTINCT ids FROM table");
?>
<table>
<?php foreach($query as $row){ ?>
<tr>
<td><?php echo $row['ids']; ?></td>
<?php
$id= $row["ids"];
$sub_inner = $database->getRows("SELECT date,Event,Event2 FROM table where ids= :ids",
array(':ids'=>$id));
?>
<td><?php foreach($sub_inner as $list){ ?><?php echo $list['date']; ?></td><td><?php echo $list['Event']; ?><?php } ?></td>
<td><?php echo $list['Event2']; ?></td>
<?php } ?>
关于 PIVOT 方法的详细信息。
有用的答案:
Using PIVOT in SQL Server 2008
MSSQL dynamic pivot column values to column header
试试这个代码:
-- Temporary table...
create table ##myTable (
IDs int
,[Date] datetime
,[Event] varchar(1)
)
-- ... with sample data
insert ##myTable
select 102, '2010-01-01', 'A'
union select 102, '2010-01-01', 'B'
union select 102, '2010-01-01', 'C'
union select 102, '2010-01-01', 'E'
union select 103, '2010-01-01', 'A'
union select 104, '2010-01-01', 'B'
union select 104, '2010-01-01', 'C'
union select 105, '2010-01-01', 'F'
-- Variables
DECLARE @cols AS NVARCHAR(MAX)
,@query AS NVARCHAR(MAX)
-- Build column name for our result.
-- The ROW_NUMBER() operator gives us the rank of the event for
-- the combination of IDs and Date. With that, event B for IDs 104
-- will have rank 1, and then will appear in the 1st column.
SELECT @cols = STUFF(
(SELECT DISTINCT
',' + QUOTENAME('Event' + LTRIM(STR(
ROW_NUMBER() OVER (
PARTITION BY IDs, [Date]
ORDER BY IDs, [Date]
)
)))
FROM ##myTable
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
, 1, 1, '')
set @query = '
SELECT IDs, [Date], ' + @cols + '
FROM (
SELECT IDs
,[Date]
,[Event]
,''Event'' + LTRIM(STR(
ROW_NUMBER() OVER (
PARTITION BY IDs, [Date]
ORDER BY IDs, [Date]
)
)) as [EventNo]
FROM ##myTable
) x
PIVOT
(
MAX([Event])
FOR [EventNo] IN (' + @cols + ')
) p'
execute sp_executesql @query
-- Remove temporary table
drop table ##myTable
结果: