问题
I have a following table (a simplified example, in fact the table contains multiple IDs, with variable numbers of dates, and variable number of events for each date):
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
I am trying to get a table where I will have distinct IDs/Date pairs, with the rows for which there have been multiple events recoded being transposed into columns. So, I'm looking for a table which for this example would look like this:
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
I'm sorry for not posting any code, but I frankly don't even know how to start with this.
回答1:
Details about PIVOT method.
And helpfull answers:
Using PIVOT in SQL Server 2008
MSSQL dynamic pivot column values to column header
Try this code:
-- 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
And the result :
![](https://i0.wp.com/i.stack.imgur.com/vVuhf.jpg)
回答2:
If you only have two events, you can do this with min()
, max()
, and some additional logic:
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;
This is standard SQL so it should work in any database.
回答3:
try this first select ids and then fetch all column based on above 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 } ?>
来源:https://stackoverflow.com/questions/28696315/transposing-rows-into-columns-based-on-a-condition-sql