根据条件 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

结果: