'SQL query using rows from another query
I would like to use the results from one query to perform another query and combine the results into a single table.
The first query obtains a set of devices for a particular device version and date
SELECT
dbo.DeviceSession.SerialNumber,
dbo.DeviceSession.BackupDate
FROM
dbo.DeviceSession
| SerialNumber | BackupDate |
|---|---|
| 1 | 2022-01-24 |
| 2 | 2022-02-08 |
| 3 | 2022-02-10 |
The second query obtains the number of errors for a particular serial number and backup date.
SELECT
ErrorCode, COUNT(*) AS [Count]
FROM
dbo.DeviceSession FULL OUTER JOIN
dbo.DeviceSessionErrorLogEntry AS DeviceSessionErrorEntry_1
ON DeviceSession.Id = DeviceSessionErrorEntry_1.DeviceSessionId
WHERE
(dbo.DeviceSession.DeviceSerial LIKE '1') AND
(dbo.DeviceSession.BackupDate LIKE '2022-01-24')
GROUP BY ErrorCode
| ErrorCode | Count |
|---|---|
| 97 | 2 |
| 150 | 5 |
The second query can be combined into a single line by using the "FOR XML PATH('')"
SELECT
ErrorCode, COUNT(*) AS [Count]
FROM
dbo.DeviceSession
FULL OUTER JOIN
dbo.DeviceSessionErrorLogEntry AS DeviceSessionErrorEntry_1
ON DeviceSession.Id = DeviceSessionErrorEntry_1.DeviceSessionId
WHERE
(dbo.DeviceSession.DeviceSerial LIKE '1')
AND (dbo.DeviceSession.BackupDate LIKE '2022-01-24')
GROUP BY ErrorCode
FOR XML PATH('')
| XML_FDEWFJEWFOE |
|---|
| <ErrorCode>97</ErrorCode><Count>2</Count><ErrorCode>150</ErrorCode><Count>5</Count> |
How would I create a query such that I could obtain a table that lists the total errors for every serial number and backup date from the first query?
Desired output:
| SerialNumber | BackupDate | Notes |
|---|---|---|
| 1 | 2022-01-24 | <ErrorCode>97</ErrorCode><Count>2</Count><ErrorCode>150</ErrorCode><Count>5</Count> |
| 2 | 2022-02-08 | <ErrorCode>97</ErrorCode><Count>5</Count> |
| 3 | 2022-02-10 | <ErrorCode>42</ErrorCode><Count>1</Count> |
Solution 1:[1]
You can move your error log query into a correlated subquery that references DeviceSession in the outer query. Something like the following:
DECLARE @DeviceSession TABLE (ID INT, SerialNumber INT, BackupDate DATE)
INSERT @DeviceSession
VALUES
(101, 1, '2022-01-24'),
(102, 2, '2022-02-08'),
(103, 3, '2022-02-10')
DECLARE @DeviceSessionErrorLogEntry TABLE (ID INT, DeviceSessionID INT, ErrorCode INT)
INSERT @DeviceSessionErrorLogEntry
VALUES
(201, 101, 97),
(202, 101, 150),
(203, 101, 150),
(204, 101, 97),
(205, 101, 150),
(206, 102, 97),
(207, 102, 150),
(208, 102, 150)
SELECT
DS.SerialNumber,
DS.BackupDate,
Notes = (
SELECT EL.ErrorCode, COUNT(*) AS [Count]
FROM @DeviceSessionErrorLogEntry EL
WHERE DS.Id = EL.DeviceSessionId
GROUP BY EL.ErrorCode
ORDER BY EL.ErrorCode
FOR XML PATH(''), TYPE
)
FROM @DeviceSession DS
ORDER BY DS.SerialNumber
Results:
| SerialNumber | BackupDate | Notes |
|---|---|---|
| 1 | 2022-01-24 | <ErrorCode>97</ErrorCode><Count>2</Count><ErrorCode>150</ErrorCode><Count>3</Count> |
| 2 | 2022-02-08 | <ErrorCode>97</ErrorCode><Count>1</Count><ErrorCode>150</ErrorCode><Count>2</Count> |
| 3 | 2022-02-10 | NULL |
The subquery can also be moved to a CROSS APPLY if you would like to separate subquery details from the final select for readability.
If you really need a full outer join (to show error records that have no matching session), the query would need some restructuring with an FULL OUTER JOIN (SELECT DISTINCT DeviceSessionId FROM @DeviceSessionErrorLogEntry EL) IDS ON IDS.DeviceSessionId = DS.Id, and then have the Notes subquery reference those IDs.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
