在返回一个ROW的上一个选择之后选择特定的COLUMNS

时间:2016-09-12 18:49:58

标签: sql sql-server-2008

我完全被困在这里,需要帮助。

我有一个名为“2016Blocks”的表这个表有每个人的行。每行都有一年中每天的列(每行365列)。

我目前有一个select语句,它将返回一行如下所示:

SELECT * FROM [2016Blocks] WHERE ([OfficialID] = @OfficialID)

上面的select语句将返回一行包含365列。每列将为空白或包含日期。列的名称是(Blocks1,Blocks2,Blocks3 ...... Blocks365)

我现在想在此行上执行另一个select语句,只返回其中包含日期的列。

我该怎么做?

2 个答案:

答案 0 :(得分:0)

您必须使用UNPIVOT功能。由于您有365列,因此您可能不想提及365个硬编码列名称。为此,您可以使用动态查询。最后,您可以在子查询中使用以下查询或在临时表中插入记录并为BlockValue添加过滤器。希望这会有所帮助。

DECLARE @colsUnpivot AS NVARCHAR(MAX),
   @query  AS NVARCHAR(MAX)

select @colsUnpivot 
  = stuff((select ','+quotename(C.column_name)
           from information_schema.columns as C
           where C.table_name = '2016Blocks' and
                 C.column_name like 'Blocks%'
           for xml path('')), 1, 1, '')

set @query 
  = 'select id, entityId,
        BlockNumber,
        BlockValue
     from 2016Blocks
     WHERE ([OfficialID] = @OfficialID)
     unpivot
     (
        BlockValue
        for BlockNumber in ('+ @colsunpivot +')
     ) u'

exec sp_executesql @query;

答案 1 :(得分:0)

您可以通过XML执行此操作。 Null将被删除,无需指定所有365个字段

Declare @2016Blocks table (OfficialID int ,Block1 Date,Block2 Date,Block365 Date)
Insert into @2016Blocks values
(1,'2016-01-01','2016-01-02',null),
(2,'2016-06-15','2016-07-02','2016-08-22')

Declare @XML xml
Set @XML = (Select * from @2016Blocks for XML RAW)

Select ID    = r.value('@OfficialID','int')
      ,Item  = attr.value('local-name(.)','varchar(100)')
      ,Value = attr.value('.','varchar(max)') 
 From  @XML.nodes('/row') as A(r)
 Cross Apply A.r.nodes('./@*[local-name(.)!="OfficialID"]') as B(attr)

返回

ID  Item        Value
1   Block1      2016-01-01
1   Block2      2016-01-02
2   Block1      2016-06-15
2   Block2      2016-07-02
2   Block365    2016-08-22
  

修改

**

  

我添加了ID和字段名称来演示功能**