我已存储记录了类型和日期的数据。我想获取每个日期每种类型的总数。我有一个具有以下模式的表:
Id | Type | Date_and_Time |
----------------------------------------
1 | Bags | 2019-01-01 17:39:34.620 |
2 | Shoes | 2019-01-02 17:39:34.620 |
3 | Shoes | 2019-01-02 17:39:34.620 |
4 | Bags | 2019-01-02 17:39:34.620 |
5 | Shirts | 2019-01-02 17:39:34.620 |
6 | Shirts | 2019-01-03 17:39:34.620 |
7 | Shirts | 2019-01-03 17:39:34.620 |
...
我有有效的PIVOT查询,但没有日期过滤器:
DECLARE @cols NVARCHAR(max) = Stuff((SELECT DISTINCT ', ' + Quotename(Type)
FROM #Tempsa
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, NULL);
EXECUTE('SELECT * FROM (select CAST(Date_and_Time as DATE) AS Transaction_Date, Type, Count(*) n
from #Tempsa GROUP BY CAST(Date_and_Time as DATE), Type) s
PIVOT (max(n) FOR Type IN (' +@cols + ')) pvt')
Output :
Transaction_Date | Bags | Shirts | Shoes
------------------------------------------
| 2019-01-01 | 1 | NULL | NULL |
| 2019-01-02 | 1 | 1 | 2 |
| 2019-01-03 | NULL | 2 | NULL |
....
但是,当我在日期过滤器之间使用以下查询时,没有任何记录:
DECLARE @STARTDATE nvarchar(100) = '01/01/2019'
DECLARE @ENDDATE nvarchar(100) = '01/03/2019'
DECLARE @cols NVARCHAR(max) = Stuff((SELECT DISTINCT ', ' + Quotename(Type)
FROM #Tempsa
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, NULL);
EXECUTE('SELECT * FROM (select CAST(Date_and_Time as DATE) AS Transaction_Date, Type, Count(*) n
from #Tempsa WHERE Date_and_Time BETWEEN ' +@STARTDATE+ ' AND ' +@ENDDATE+' GROUP BY CAST(Date_and_Time as DATE), Type) s
PIVOT (max(n) FOR Type IN (' +@cols + ')) pvt')
Output :
Transaction_Date | Bags | Shirts | Shoes
------------------------------------------
| | | | |
....
答案 0 :(得分:6)
只需在日期前后加上引号即可
DECLARE @STARTDATE nvarchar(100) = '01/01/2019'
DECLARE @ENDDATE nvarchar(100) = '01/03/2019'
DECLARE @cols NVARCHAR(max) = Stuff((SELECT DISTINCT ', ' + Quotename(Type)
FROM #Tempsa
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, NULL);
EXECUTE('SELECT * FROM (select CAST(Date_and_Time as DATE) AS Transaction_Date, Type, Count(*) n
from #Tempsa WHERE Date_and_Time BETWEEN ''' +@STARTDATE+ ''' AND ''' +@ENDDATE+''' GROUP BY CAST(Date_and_Time as DATE), Type) s
PIVOT (max(n) FOR Type IN (' +@cols + ')) pvt')
没有双引号,您正在构建如下内容:
BETWEEN 01/01/2011 AND 01/03/2019
这只是由引擎评估的计算
SELECT 01/01/2011 -- 0
,01/03/2019 -- 0
,它是0
。因此,您要求获取从0
到0
的所有日期。
这就是为什么添加引号会使您的过滤条件有效(以前有效,但是SELECT CAST(0 AS DATETIME)
是1900-01-01 00:00:00.000
,并且由于边界相同,因此不会返回记录)。
当然,您可以使用CONVERT(VARCHAR(10), @STARTDATE, 121)
来确保在隐式转换过程中没有任何误解。
答案 1 :(得分:1)
我已经修改了您共享的查询以获得所需的结果。它无法正常工作,因为在合并过滤器的日期时缺少一个非常好的单。现在正在工作。您可以验证相同。
DECLARE @STARTDATE nvarchar(100) = '01/01/2019'
DECLARE @ENDDATE nvarchar(100) = '01/03/2019'
DECLARE @cols NVARCHAR(max) = Stuff((SELECT DISTINCT ', ' + Quotename(Type)
FROM #Tempsa
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, NULL);
EXECUTE( 'SELECT * FROM (select CAST(Date_and_Time as DATE) AS Transaction_Date, Type, Count(*) n
from #Tempsa WHERE Date_and_Time BETWEEN ''' + @STARTDATE+ ''' AND ''' +@ENDDATE+''' GROUP BY CAST(Date_and_Time as DATE), Type) s
PIVOT (max(n) FOR Type IN (' +@cols + ')) pvt')
答案 2 :(得分:0)
将日期写成ISO格式,这样就不会混淆月份和日期。
DECLARE @STARTDATE nvarchar(100) = '2019-01-01'
DECLARE @ENDDATE nvarchar(100) = '2019-01-03'
并确保(以防万一)在动态SQL上进行显式转换。同样,将SQL设置为变量并在执行(使用PRINT)之前先预览它也是一种好方法:
DECLARE @DynamicSQL NVARCHAR(MAX) = '
SELECT * FROM (select CAST(Date_and_Time as DATE) AS Transaction_Date, Type, Count(*) n
from #Tempsa WHERE Date_and_Time BETWEEN CONVERT(DATE, ''' +@STARTDATE+ ''') AND CONVERT(DATE, ''' + @ENDDATE +''')
GROUP BY CAST(Date_and_Time as DATE), Type) s
PIVOT (max(n) FOR Type IN (' +@cols + ')) pvt'
PRINT (@DynamicSQL)
-- EXECUTE(@DynamicSQL)
答案 3 :(得分:0)
为简化查询,您可以将sp_executesql
与如下参数一起使用。
DECLARE @STARTDATE nvarchar(100) = '01/01/2019'
DECLARE @ENDDATE nvarchar(100) = '01/03/2019'
DECLARE @cols NVARCHAR(max) = Stuff((SELECT DISTINCT ', ' + Quotename(Type)
FROM #Tempsa
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, NULL);
declare @SQLString Nvarchar(max)= N'SELECT * FROM (select CAST(Date_and_Time as DATE) AS Transaction_Date, Type, Count(*) n
from #Tempsa WHERE Date_and_Time BETWEEN @SD AND @ED GROUP BY CAST(Date_and_Time as DATE), Type) s
PIVOT (max(n) FOR Type IN (' +@cols + ')) pvt'
exec sp_executesql @SQLString,N'@SD DATE,@ED DATE',@SD=@STARTDATE,@ED=@ENDDATE