如何在PIVOT SQL查询之间添加日期过滤器

Ric*_*ard 6 sql t-sql sql-server

我已经存储了记录类型和日期的数据.我想得到每个日期的每种类型的总数.我有一个具有以下模式的表:

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 |  
...
Run Code Online (Sandbox Code Playgroud)

我有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 |
....  
Run Code Online (Sandbox Code Playgroud)

但是,当我在日期过滤器之间使用以下查询时,我没有得到任何记录:

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
------------------------------------------
|                |       |        |       |
....
Run Code Online (Sandbox Code Playgroud)

got*_*tqn 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')
Run Code Online (Sandbox Code Playgroud)

没有双引号,你正在构建这样的东西:

BETWEEN 01/01/2011 AND 01/03/2019
Run Code Online (Sandbox Code Playgroud)

这只是由引擎评估的计算

 SELECT 01/01/2011 -- 0
       ,01/03/2019 -- 0
Run Code Online (Sandbox Code Playgroud)

它是0.所以,你问要获取的是从所有日期00.这就是为什么加引号让你的过滤标准有效(这是以前有效,但SELECT CAST(0 AS DATETIME)就是1900-01-01 00:00:00.000和你的界限都是一样的,没有记录返回).

当然,您可以使用CONVERT(VARCHAR(10), @STARTDATE, 121)以确保在隐式转换期间不存在误解.