gpt4 book ai didi

sql - 在 SQL Server 2017 中将行转换为带有条件的列

转载 作者:行者123 更新时间:2023-12-02 10:55:40 25 4
gpt4 key购买 nike

我在 SQL Server 中有 2 个表,我希望将一些行转置为列,按 ID/Name 顺序(以对我来说合适的为准)并按 排序>日期

[dbo].[USERINFO]:

+--------+-------------+---------+
| USERID | BADGENUMBER | NAME |
+--------+-------------+---------+
| 1 | 1000 | BEN |
+--------+-------------+---------+
| 2 | 1111 | ANNE |
+--------+-------------+---------+

[dbo].[CHECKINOUT]:

+--------+-------------------------+
| USERID | CHECKTIME |
+--------+-------------------------+
| 1 | 2019-02-16 08:01:39.000 |
+--------+-------------------------+
| 1 | 2019-02-16 13:05:21.000 |
+--------+-------------------------+
| 1 | 2019-02-16 14:42:23.000 |
+--------+-------------------------+
| 1 | 2019-02-16 17:07:55.000 |
+--------+-------------------------+
| 1 | 2019-02-18 07:56:23.000 |
+--------+-------------------------+
| 1 | 2019-02-18 19:48:23.000 |
+--------+-------------------------+
| 2 | 2019-02-16 07:43:57.000 |
+--------+-------------------------+
| 2 | 2019-02-16 12:30:04.000 |
+--------+-------------------------+
| 2 | 2019-02-18 06:52:55.000 |
+--------+-------------------------+
| 2 | 2019-02-18 18:01:41.000 |
+--------+-------------------------+
| 2 | 2019-02-19 07:55:17.000 |
+--------+-------------------------+
| 2 | 2019-02-19 12:30:08.000 |
+--------+-------------------------+
| 2 | 2019-02-20 07:52:15.000 |
+--------+-------------------------+
| 2 | 2019-02-20 17:51:49.000 |
+--------+-------------------------+

我期待这样的结果。

+------+------+------------+----------+----------+----------+----------+--------+
| ID | Name | Date | Time1 | Time2 | Time3 | Time4 | Time5 |
+------+------+------------+----------+----------+----------+----------+--------+
| 1111 | ANNE | 16/02/2019 | 07:43:57 | 12:30:04 | NULL | NULL | NULL |
+------+------+------------+----------+----------+----------+----------+--------+
| 1111 | ANNE | 18/02/2019 | 06:52:55 | 18:01:41 | NULL | NULL | NULL |
+------+------+------------+----------+----------+----------+----------+--------+
| 1111 | ANNE | 19/02/2019 | 07:55:17 | 12:30:08 | NULL | NULL | NULL |
+------+------+------------+----------+----------+----------+----------+--------+
| 1111 | ANNE | 20/02/2019 | 07:52:15 | 17:51:49 | NULL | NULL | NULL |
+------+------+------------+----------+----------+----------+----------+--------+
| 1000 | BEN | 16/02/2019 | 08:01:39 | 13:05:21 | 14:42:23 | 17:07:55 | NULL |
+------+------+------------+----------+----------+----------+----------+--------+
| 1000 | BEN | 18/02/2019 | 07:56:23 | 19:48:23 | NULL | NULL | NULL |
+------+------+------------+----------+----------+----------+----------+--------+

ORDER BY ID 或 ORDER BY Name 都可以。

到目前为止我已经尝试过了

SELECT *
INTO #Temp
FROM (
SELECT U.BADGENUMBER as ID, U.[NAME] as Name,
CONVERT(VARCHAR(10),C.CHECKTIME, 103) [Date],
CONVERT(VARCHAR(8), C.CHECKTIME, 108) [Time]
FROM [CHECKINOUT] as C JOIN [USERINFO] as U
ON C.USERID = U.USERID
) AS x
SELECT ID, Name, Date, [1] as Time1, [2] as Time2, [3] as Time3,
[4] as Time4, [5] as Time5, [6] as Time6, [7] as Time7, [8] as Time8, [9] as Time9
FROM ( SELECT
ID, Name, Date, Time,
row_number() over (partition by Name order by Date) as rn
from #Temp
) s

PIVOT (
MAX([Time]) for rn in ([1], [2], [3], [4], [5], [6], [7], [8], [9])
) as pvt
ORDER BY ID

DROP TABLE #Temp

基于此link

相反,我得到了这样的结果,

+------+------+------------+----------+----------+----------+----------+----------+
| ID | Name | Date | Time1 | Time2 | Time3 | Time4 | Time5 |
+------+------+------------+----------+----------+----------+----------+----------+
| 1111 | ANNE | 16/02/2019 | 07:43:57 | 12:30:04 | NULL | NULL | NULL |
+------+------+------------+----------+----------+----------+----------+----------+
| 1111 | ANNE | 18/02/2019 | NULL | NULL | 06:52:55 | 18:01:41 | NULL |
+------+------+------------+----------+----------+----------+----------+----------+
| 1111 | ANNE | 19/02/2019 | NULL | NULL | NULL | NULL | 07:55:17 |
+------+------+------------+----------+----------+----------+----------+----------+
| 1111 | ANNE | 20/02/2019 | NULL | NULL | NULL | NULL | NULL |
+------+------+------------+----------+----------+----------+----------+----------+
| 1000 | BEN | 16/02/2019 | 08:01:39 | 13:05:21 | 14:42:23 | 17:07:55 | NULL |
+------+------+------------+----------+----------+----------+----------+----------+
| 1000 | BEN | 18/02/2019 | NULL | NULL | NULL | NULL | 07:56:23 |
+------+------+------------+----------+----------+----------+----------+----------+

我哪里做错了?请大家帮我指点一下。提前致谢。问候。

最佳答案

问题来自于 ROW_NUMBER() 函数的 OVER() 子句。您还需要按 [Date] 分区,而不仅仅是按用户分区。您还想按[时间]订购。

您需要更改此设置:

row_number() over (partition by Name order by Date) as rn

致:

row_number() over (partition by  [Date], Name order by [Time]) as rn as rn

<强> Demo on DB Fiddle :

  ID | Name | Date       | Time1    | Time2    | Time3    | Time4    | Time5 | Time6 | Time7 | Time8 | Time9---: | :--- | :--------- | :------- | :------- | :------- | :------- | :---- | :---- | :---- | :---- | :----1000 | BEN  | 16/02/2019 | 08:01:39 | 13:05:21 | 14:42:23 | 17:07:55 | null  | null  | null  | null  | null 1000 | BEN  | 18/02/2019 | 07:56:23 | 19:48:23 | null     | null     | null  | null  | null  | null  | null 1111 | ANNE | 16/02/2019 | 07:43:57 | 12:30:04 | null     | null     | null  | null  | null  | null  | null 1111 | ANNE | 18/02/2019 | 06:52:55 | 18:01:41 | null     | null     | null  | null  | null  | null  | null 1111 | ANNE | 19/02/2019 | 07:55:17 | 12:30:08 | null     | null     | null  | null  | null  | null  | null 1111 | ANNE | 20/02/2019 | 07:52:15 | 17:51:49 | null     | null     | null  | null  | null  | null  | null 

Also, I would suggest another solution for this problem, that uses conditional aggregation instead of PIVOT. The latter is vendor-specific, while the former is supported by most RDBMS. If also find that this syntax is easier to read:

SELECT
badgenumber,
name,
[Date],
MAX(CASE WHEN rn = 1 THEN [Time] END) AS Time1,
MAX(CASE WHEN rn = 2 THEN [Time] END) AS Time2,
MAX(CASE WHEN rn = 3 THEN [Time] END) AS Time3,
MAX(CASE WHEN rn = 4 THEN [Time] END) AS Time4,
MAX(CASE WHEN rn = 5 THEN [Time] END) AS Time5
FROM (
SELECT
u.badgenumber,
u.name,
CAST(checktime AS DATE) as [Date],
CAST(checktime AS TIME) as [Time],
ROW_NUMBER() OVER(PARTITION BY u.badgenumber, CAST(checktime AS DATE) ORDER BY c.checktime) rn
FROM userinfo u
INNER JOIN checkinout c ON c.userid = u.userid
) x
GROUP BY badgenumber, name, [Date]

<强> Demo on DB Fiddle

关于sql - 在 SQL Server 2017 中将行转换为带有条件的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55530497/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com