用 SQL 替代 STRING_AGG
Alternative to STRING_AGG in with SQL
我有一个table如下
| activityName | UserID | deviceID | createdDate |
|------------------------------------------------------------|
| ON | 1 | adddsad |2020-01-09 00:02:59.477 |
| OFF | 1 | adddsad |2020-01-09 00:50:39.857 |
| ON | 2 | bdddsad |2020-01-09 00:51:11.480 |
| OFF | 2 | bdddsad |2020-01-09 00:51:19.450 |
当我像这样使用 STRING_AGG
时,它是准确的并且 return 是我想要的结果
SELECT STRING_AGG(activityName + ' - ' + CONVERT(varchar, createdDate), ' | ') AS tag,
deviceID,
UserID
FROM (SELECT tag,
deviceID,
UserID
FROM tbl_DailyLogMaster
WHERE CONVERT(date, createdDate) = CONVERT(date, GETDATE())
GROUP BY userID) a
GROUP BY UserID;
会return这样
| tag | deviceID | UserID |
|------------------------------------------------------------------------------------|
| ON - 2020-01-09 00:02:59.477 | OFF - 2020-01-09 00:50:39.857 | adddsad | 1 |
| ON - 2020-01-09 00:51:11.480 | OFF - 2020-01-09 00:51:19.450 | bdddsad | 2 |
在生产环境中我有 SQL Server 2014 运行 并且不得不为 STRING_AGG
开发替代方案,旧版本不支持
这是我创建的替代方案
SELECT deviceID,
UserID,
STUFF((SELECT activityName + ' - ' + CONVERT(varchar, createdDate)
FROM tbl_DailyLogMaster
WHERE userID = tbl_DailyLogMaster.UserID
AND CONVERT(date, createdDate) = CONVERT(date, GETDATE())
ORDER BY UserID
FOR XML PATH('')),1,1,'') AS tag
FROM tbl_DailyLogMaster
WHERE CONVERT(date, createdDate) = CONVERT(date, GETDATE())
GROUP BY UserID,
deviceID,
UserID,
createdDate,
activityName;
它return是这样的
| tag | deviceID | UserID |
|---------------------------------------------------------------------------------------------------------------------------------------------------------|
| N - Jan 9 2020 12:51AMOFF - Jan 9 2020 12:51AMON - Jan 9 2020 12:02AMOFF - Jan 9 2020 12:50AM | OFF - 2020-01-09 00:50:39.857 | adddsad | 1 |
| N - Jan 9 2020 12:51AMOFF - Jan 9 2020 12:51AMON - Jan 9 2020 12:02AMOFF - Jan 9 2020 12:50AM | OFF - 2020-01-09 00:50:39.857 | adddsad | 1 |
| N - Jan 9 2020 12:51AMOFF - Jan 9 2020 12:51AMON - Jan 9 2020 12:02AMOFF - Jan 9 2020 12:50AM | OFF - 2020-01-09 00:50:39.857 | bdddsad | 2 |
| N - Jan 9 2020 12:51AMOFF - Jan 9 2020 12:51AMON - Jan 9 2020 12:02AMOFF - Jan 9 2020 12:50AM | OFF - 2020-01-09 00:50:39.857 | bdddsad | 2 |
第二个查询我做错了什么?
有点瞎猜,但我认为这是正确答案。您需要确保子查询正确关联:
SELECT deviceID,
UserID,
STUFF((SELECT ' | ' + sq.activityName + ' - ' + CONVERT(varchar(20),sq.createdDate, 0)
FROM tbl_DailyLogMaster sq
WHERE DLM.UserID = sq.UserId
AND DLM.DeviceID = sq.DeviceID
AND sq.createdDate >= CONVERT(date, GETDATE())
AND sq.createdDate < DATEADD(DAY, 1, CONVERT(date, GETDATE()))
ORDER BY CreatedDate
FOR XML PATH(''),TYPE).value('.','varchar(MAX)'),1,3,'') AS tag --As yuou have no leading separator, no need for STUFF
FROM tbl_DailyLogMaster DLM
WHERE DLM.createdDate >= CONVERT(date, GETDATE())
AND DLM.createdDate < DATEADD(DAY, 1, CONVERT(date, GETDATE()))
GROUP BY UserID,
DeviceID;
我有一个table如下
| activityName | UserID | deviceID | createdDate |
|------------------------------------------------------------|
| ON | 1 | adddsad |2020-01-09 00:02:59.477 |
| OFF | 1 | adddsad |2020-01-09 00:50:39.857 |
| ON | 2 | bdddsad |2020-01-09 00:51:11.480 |
| OFF | 2 | bdddsad |2020-01-09 00:51:19.450 |
当我像这样使用 STRING_AGG
时,它是准确的并且 return 是我想要的结果
SELECT STRING_AGG(activityName + ' - ' + CONVERT(varchar, createdDate), ' | ') AS tag,
deviceID,
UserID
FROM (SELECT tag,
deviceID,
UserID
FROM tbl_DailyLogMaster
WHERE CONVERT(date, createdDate) = CONVERT(date, GETDATE())
GROUP BY userID) a
GROUP BY UserID;
会return这样
| tag | deviceID | UserID |
|------------------------------------------------------------------------------------|
| ON - 2020-01-09 00:02:59.477 | OFF - 2020-01-09 00:50:39.857 | adddsad | 1 |
| ON - 2020-01-09 00:51:11.480 | OFF - 2020-01-09 00:51:19.450 | bdddsad | 2 |
在生产环境中我有 SQL Server 2014 运行 并且不得不为 STRING_AGG
开发替代方案,旧版本不支持
这是我创建的替代方案
SELECT deviceID,
UserID,
STUFF((SELECT activityName + ' - ' + CONVERT(varchar, createdDate)
FROM tbl_DailyLogMaster
WHERE userID = tbl_DailyLogMaster.UserID
AND CONVERT(date, createdDate) = CONVERT(date, GETDATE())
ORDER BY UserID
FOR XML PATH('')),1,1,'') AS tag
FROM tbl_DailyLogMaster
WHERE CONVERT(date, createdDate) = CONVERT(date, GETDATE())
GROUP BY UserID,
deviceID,
UserID,
createdDate,
activityName;
它return是这样的
| tag | deviceID | UserID |
|---------------------------------------------------------------------------------------------------------------------------------------------------------|
| N - Jan 9 2020 12:51AMOFF - Jan 9 2020 12:51AMON - Jan 9 2020 12:02AMOFF - Jan 9 2020 12:50AM | OFF - 2020-01-09 00:50:39.857 | adddsad | 1 |
| N - Jan 9 2020 12:51AMOFF - Jan 9 2020 12:51AMON - Jan 9 2020 12:02AMOFF - Jan 9 2020 12:50AM | OFF - 2020-01-09 00:50:39.857 | adddsad | 1 |
| N - Jan 9 2020 12:51AMOFF - Jan 9 2020 12:51AMON - Jan 9 2020 12:02AMOFF - Jan 9 2020 12:50AM | OFF - 2020-01-09 00:50:39.857 | bdddsad | 2 |
| N - Jan 9 2020 12:51AMOFF - Jan 9 2020 12:51AMON - Jan 9 2020 12:02AMOFF - Jan 9 2020 12:50AM | OFF - 2020-01-09 00:50:39.857 | bdddsad | 2 |
第二个查询我做错了什么?
有点瞎猜,但我认为这是正确答案。您需要确保子查询正确关联:
SELECT deviceID,
UserID,
STUFF((SELECT ' | ' + sq.activityName + ' - ' + CONVERT(varchar(20),sq.createdDate, 0)
FROM tbl_DailyLogMaster sq
WHERE DLM.UserID = sq.UserId
AND DLM.DeviceID = sq.DeviceID
AND sq.createdDate >= CONVERT(date, GETDATE())
AND sq.createdDate < DATEADD(DAY, 1, CONVERT(date, GETDATE()))
ORDER BY CreatedDate
FOR XML PATH(''),TYPE).value('.','varchar(MAX)'),1,3,'') AS tag --As yuou have no leading separator, no need for STUFF
FROM tbl_DailyLogMaster DLM
WHERE DLM.createdDate >= CONVERT(date, GETDATE())
AND DLM.createdDate < DATEADD(DAY, 1, CONVERT(date, GETDATE()))
GROUP BY UserID,
DeviceID;