按特定月份和用户的某个月的天数枢纽化[转换]表格

时间:2019-02-17 10:30:01

标签: sql sql-server pivot transform

我有两个表分别称为Records和Users。表格设计如下。

表[记录]

用户名,用户名,IP,日期
1,murat,192.168.1.100,2019-02-17 04:12:20.470
2,murat,192.168.1.100,2019-02-17 04:33:36.120
3,迈克尔,192.168.120.175,2019-02-17 08:08:22.210

用户[用户]

用户名,名称,邮件,部门,记录,功能,级别,管理员,ManagerTop
murat,Murat,murat@asd.com,11111,IT,Software Department,1,Kobe,Michael
michael,Michael,michael@asd.com,22222,IT,Helpdesk,2,Shaq,Michael

我想做的是,将[记录]的表按一个月的天数按特定的月份和用户名旋转。

我想要的是这样的东西:

用户名,名称,ManagerTop,Manager,Month,1、2、3、4、5、6、7、8、9、10、11、12、13、14、15、16、17, 18、19、20、21、22、23、24、25、26、27、28、29、30、31
murat,穆拉特(Murat),迈克尔(Michael),神户(Kobe),2月,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不, ,不,不,不,不,不,不,不,不,不,不,不,不,不,不,不

感谢您的支持

2 个答案:

答案 0 :(得分:1)

确实可以使用PIVOT

“用户”表可以连接到数据透视表。

SELECT 
pvt.Username, 
usr.Name,
usr.ManagerTop, 
usr.Manager,
pvt.[Month], 
IIF([1]>0,'Yes','No') AS [1],
IIF([2]>0,'Yes','No') AS [2],
-- Add the other days
IIF([17]>0,'Yes','No') AS [17],
-- Add the other days
IIF([30]>0,'Yes','No') AS [30],
IIF([31]>0,'Yes','No') AS [31]
FROM
(
   SELECT
   rec.Username,  
   YEAR(rec.[Date]) AS [Year],
   DATENAME(month, rec.[Date]) AS [Month],
   DAY(rec.[Date]) AS [Day]
   FROM [Records] rec
   WHERE rec.[Date] >= DATEFROMPARTS(YEAR(GetDate()), 1, 1)
) src
PIVOT 
(
  COUNT([Day])
  FOR [Day] IN (
     [1],[2],[3],[4],[5],[6],[7],[8],
     [9],[10],[11],[12],[13],[14],[15],[16],
     [17],[18],[19],[20],[21],[22],[23],[24],
     [25],[26],[27],[28],[29],[30],[31])
) pvt
LEFT JOIN [Users] usr 
     ON usr.Username = pvt.Username
ORDER BY pvt.Username;

上个月的测试 here

答案 1 :(得分:1)

您可以使用Pivot实现此目的,为此,您需要使用CTE来生成所需的月份和日期。我写的查询假设您的日期在一年的边界之内,如果您想扩展到多年,则可以通过在最小日期和最大日期之间生成年份来轻松实现。

declare @table1 table(Id int, Username varchar(100), IP varchar(20), [Date] datetime)
insert into @table1 select 1, 'murat'   , '192.168.1.100', '2019-02-17 04:12:20.470'
insert into @table1 select 2, 'murat'   , '192.168.1.100', '2019-02-17 04:33:36.120'
insert into @table1 select 3, 'michael', '192.168.120.175', '2019-02-17 08:08:22.210'

declare @table2 table( Username varchar(100), Name varchar(100), Mail varchar(100), Department varchar(100), Record varchar(100), [Function] varchar(100), [Level] int , Manager varchar(100), ManagerTop varchar(100))
insert into @table2 select 'murat', 'Murat', 'murat@asd.com', '11111', 'IT', 'Software Department', 1, 'Kobe', 'Michael'
insert into @table2 select 'michael', 'Michael', 'michael@asd.com', '22222', 'IT', 'Helpdesk', 2, 'Shaq', 'Michael'

;WITH cte(months) 
     AS (SELECT 1 
         UNION ALL 
         SELECT months + 1 
         FROM   cte 
         WHERE  months < 31), 
     n(n) 
     AS (SELECT 1 
         UNION ALL 
         SELECT n + 1 
         FROM   n 
         WHERE  n < 31), 
     cte2 
     AS (SELECT C.months AS CM, 
                n.n      AS CD 
         FROM   cte C 
                CROSS JOIN n), 
     cte3 
     AS (SELECT username, 
                NAME, 
                managertop, 
                mname, 
                t2.[date], 
                C2.cd, 
                CASE 
                  WHEN Month(date) = C2.cm 
                       AND Day(date) = cd THEN 'Yes' 
                  ELSE 'No' 
                END Present, 
                rn 
         FROM   cte2 C2 
                INNER JOIN (SELECT [date], 
                                   T1.username, 
                                   T2.NAME, 
                                   T2.managertop, 
                                   Datename(month, Dateadd(month, Month([date]),0)- 1) 
                                   Mname, 
                                   Row_number() 
                                     OVER ( 
                                       partition BY T1.username 
                                       ORDER BY T1.date) 
                                   RN 
                            FROM   @table1 T1 
                                   INNER JOIN @table2 T2 
                                           ON T1.username = T2.username)T2 
                        ON Month(t2.date) = C2.cm) 
SELECT username, 
       NAME, 
       managertop, 
       mname AS [Month], 
       [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31]
FROM   (SELECT * 
        FROM   cte3 
        WHERE  rn = 1) AS SourceTable 
       PIVOT ( Max(present) 
             FOR cd IN ( [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31]) ) AS pivottable; 

Online Demo

输出

+----------+---------+------------+----------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| username | NAME    | managertop | Month    | 1  | 2  | 3  | 4  | 5  | 6  | 7  | 8  | 9  | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17  | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
+----------+---------+------------+----------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| michael  | Michael | Michael    | February | No | No | No | No | No | No | No | No | No | No | No | No | No | No | No | No | Yes | No | No | No | No | No | No | No | No | No | No | No | No | No | No |
+----------+---------+------------+----------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| murat    | Murat   | Michael    | February | No | No | No | No | No | No | No | No | No | No | No | No | No | No | No | No | Yes | No | No | No | No | No | No | No | No | No | No | No | No | No | No |
+----------+---------+------------+----------+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+