如何在sql

时间:2018-06-05 09:34:41

标签: sql sql-server

我的Product表中有两列: -

  Product          |       Date
--------------------------------------
     Prod1       |     06/01/2018
     Prod2       |     06/03/2018
     Prod3       |     06/05/2018

我希望输出为: -

 Product | 06/01/2018 | 06/02/2018 | 06/03/2018| 06/04/2018 | 06/05/2018
-------------------------------------------------------------------------
     Prod1 |     X           -            -           -            -
     Prod2 |     -           -            X           -            -
     Prod3 |     -           -            -           -            X

我想在网格中显示此表格。这可以通过在sql中编写查询来实现吗?

2 个答案:

答案 0 :(得分:1)

使用Dynamic Sql

IF OBJECT_ID('tempdb..#Temp')IS NOT NULL 
DROP TABLE #Temp
DECLARE @temp AS TABLE (Product varchar(10), [Date] DATE)

INSERT INTO @temp
 SELECT 'Product1',    '06/01/2018' UNION ALL
 SELECT 'Product2',    '06/03/2018' UNION ALL
 SELECT 'Product3',    '06/05/2018' 

DECLARE @StartDate DATE,
        @EndDate DATE      

SELECT @StartDate=MIN([Date])
        ,@EndDate=MAX([Date]) 
FROM @temp

;WITH CTE
AS
(
SELECT DISTINCT Number,
        DATEADD(DAY,Number,@StartDate) AS ReqDays
FROM master.dbo.spt_values WHERE Number BETWEEN 0 AND 100
    AND DATEADD(DAY,Number,@StartDate) BETWEEN @StartDate  AND @EndDate
)
SELECT  Product,
        ReqDays  AS [Date] INTO #Temp 
FROM CTE c
LEFT JOIN @temp t
On c.ReqDays=t.[Date]

DECLARE @Sql nvarchar(max),
        @Col  nvarchar(max),
        @Col2  nvarchar(max)

SELECT @Col=STUFF((SELECT DISTINCT ', '+QUOTENAME([Date]) FROM #Temp FOR XML PATH ('')),1,1,'')
SELECT @Col2=STUFF((SELECT DISTINCT ', '+'ISNULL('+QUOTENAME([Date])+','' '') AS '+QUOTENAME([Date]) FROM #Temp FOR XML PATH ('')),1,1,'')

SET @Sql='
SELECT Product,'+@Col2+'
FROM
(
SELECT *,IIF(DATALENGTH(Product)>0,''X'','''') AS Producttemp FROM #Temp
)AS Src
PIVOT 
(MAX([Producttemp]) FOR [Date] IN ('+@Col+')
)AS PVT WHERE Product IS NOT NULL'
PRINT @Sql
EXEC (@Sql)

结果

Product     2018-06-01  2018-06-02  2018-06-03  2018-06-04  2018-06-05
-------------------------------------------------------------------------
Product1        X                
Product2                                X        
Product3                                                        X

答案 1 :(得分:0)

这是一个将动态SQL与PIVOT结合使用的示例。

除了生成列名的方式略有不同。

使用sp_executesql代替EXEC。

--
-- Using a temporary table for testing reasons
--
if object_id('tempdb..#Test_Products')IS NOT NULL DROP TABLE #Test_Products;
create table #Test_Products (Product varchar(30), [Date] date);

--
-- Sample data
--
insert into #Test_Products (Product, [Date]) values
('Prod1', '2018-06-01'),
('Prod2', '2018-06-03'),
('Prod3', '2018-06-05');

--
-- Getting the begindate and enddate. This can also be set to hardcoded values.
--
declare @BeginDate date = (select min([Date]) from #Test_Products);
declare @EndDate date = (select max([Date]) from #Test_Products);

declare @SQL nvarchar(800);
declare @ColNames varchar(500);

--
-- Using a Recursive SQL to get all dates, then use those to get the column names
--
with RCTE as 
(
  select @BeginDate as startdate
  union all
  select dateadd(day,1,startdate)
  from RCTE where startdate < @EndDate
)
select @ColNames = concat(@ColNames+', ', quotename(convert(varchar,startdate,101))) 
from RCTE;

--
-- Generating the Dynamic SQL statement
--
set @SQL = 'select *
from 
(
  select Product, convert(varchar(10),[Date],101) as DateStamp, ''X'' as X
  from #Test_Products
  where [Date] between @BeginDate and @EndDate
  group by Product, [Date]
) src
pivot (
  max(X)
  for DateStamp 
  in ('+ @ColNames +')
) as pvt';

-- select @SQL as SQL;

EXEC sp_executesql @SQL,
        N'@BeginDate date, @EndDate date', 
        @BeginDate = @BeginDate, 
        @EndDate = @EndDate;

<强>结果:

Product 06/01/2018 06/02/2018 06/03/2018 06/04/2018 06/05/2018
------- ---------- ---------- ---------- ---------- ----------
Prod1   X          NULL       NULL       NULL       NULL
Prod2   NULL       NULL       X          NULL       NULL
Prod3   NULL       NULL       NULL       NULL       X