基于sql条件将行转换为列
我有一个下表(一个简化的示例,事实上,该表包含多个ID,日期数可变,每个日期的事件数可变): 我试图得到一个表,其中我将有不同的ID/日期对,其中有多个事件被重新编码的行被转置到列中。因此,我正在寻找一个表,在本例中,该表如下所示:基于sql条件将行转换为列,sql,duplicates,transpose,Sql,Duplicates,Transpose,我有一个下表(一个简化的示例,事实上,该表包含多个ID,日期数可变,每个日期的事件数可变): 我试图得到一个表,其中我将有不同的ID/日期对,其中有多个事件被重新编码的行被转置到列中。因此,我正在寻找一个表,在本例中,该表如下所示: IDs Date Event Event2 Event3 102 1996-10-16 00:00:00 A NULL NULL 102 1996-10-23 00:00:00 A
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;
选择ID、日期、分钟(事件)作为事件,
(最小(事件)最大(事件)然后最大(事件)结束时的情况)作为事件2
来自表t
按ID、日期分组;
这是标准SQL,因此它应该可以在任何数据库中工作。如果您只有两个事件,则可以使用
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;
选择ID、日期、分钟(事件)作为事件,
(最小(事件)最大(事件)然后最大(事件)结束时的情况)作为事件2
来自表t
按ID、日期分组;
这是标准的SQL,所以它应该可以在任何数据库中工作。尝试此操作,首先选择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 } ?>
首先尝试选择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 } ?>
有关方法的详细信息
以及完整的答案:
请尝试以下代码:
-- 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
结果是:
有关方法的详细信息
以及完整的答案:
请尝试以下代码:
-- 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
结果是:
不幸的是,事件的数量会有很大的差异。大多数ID/日期只有1个,但可能有一些ID/日期对最多有10个事件。不幸的是,事件的数量差异很大。大多数ID/日期只有1个,但可能有一些ID/日期对最多有10个事件。谢谢您的建议。我承认这远远超出了我目前的sql知识水平。。。但我有一个问题。它为每个可能的事件生成一列。因此,如果我在整个数据集中有100个不同的事件,它将产生100列,而大多数动物只有几个条目。是否不可能有一个类似的表,而不是有一个特定的事件类型作为列,而是有“Event1”、“Event2”等?这将大大节省空间!嗯,也许你可以用其他例子来完善你的问题。您想在不同行的同一列“Event 1”中查看事件A和事件B(某种程度上将结果减少为有用的列),还是希望使用规范化的列名(或两者兼有)?我现在编辑了这个问题,希望它能更好地显示我所追求的。事件列的总数应为给定ID/日期对记录的最大事件数,而不是数据中重新编码的不同事件数。因此,在本例中,我记录了4个不同的事件,但同一个人在同一天只记录了3个,因此我要查找的列数是3。我根据您上次的精度更新了查询。这正是我要查找的!非常感谢。再问一两个问题。首先,列的顺序是随机的,即我得到Event14、Event2、Event10等。。。这是一个装饰性的东西,但我只是想检查一下,这不是一个问题的迹象?第二,我从未使用过这样的语法,我有点困惑,当我想保存表格时,我应该把“into”语句放在哪里……谢谢你的建议。我承认这远远超出了我目前的sql知识水平。。。但我有一个问题。它为每个可能的事件生成一列。因此,如果我在整个数据集中有100个不同的事件,它将产生100列,而大多数动物只有几个条目。是否不可能有一个类似的表,而不是有一个特定的事件类型作为列,而是有“Event1”、“Event2”等?这将大大节省空间!嗯,也许你可以用其他例子来完善你的问题。您想在不同行的同一列“Event 1”中查看事件A和事件B(某种程度上将结果减少为有用的列),还是希望使用规范化的列名(或两者兼有)?我现在编辑了这个问题,希望它能更好地显示我所追求的。事件列的总数应为给定ID/日期对记录的最大事件数,而不是数据中重新编码的不同事件数。因此,在本例中,我记录了4个不同的事件,但同一个人在同一天只记录了3个,因此我要查找的列数是3。我根据您上次的精度更新了查询。这正是我要查找的!非常感谢。再问一两个问题。首先,列的顺序是随机的,即我得到Event14、Event2、Event10等。。。这是一个装饰性的东西,但我只是想检查一下,这不是一个问题的迹象?第二,我从未使用过这样的语法,我有点困惑,当我想保存表时,应该把“into”语句放在哪里。。。