My guess is the question is something like:
I have a table that looks something like this:
+----+----------+----------+---------+
| ID | Status | Approved | Request |
+----+----------+----------+---------+
| 1 | NULL | 5 | NULL |
| 1 | Approved | NULL | NULL |
| 1 | NULL | NULL | 10 |
+----+----------+----------+---------+
And you are looking to combine all these rows into just the NON-Null values for each column. Something like:
+----+----------+----------+---------+
| ID | Status | Approved | Request |
+----+----------+----------+---------+
| 1 | Approved | 5 | 10 |
+----+----------+----------+---------+
For the purpose of the examples I will show below I have created the below table. (For the sake of cleanup ease on my side I am using Table Variables instead of a physical/temp table.)
DECLARE @Table TABLE
(
ID INT,
[Status] VarChar(20) NULL,
Approved INT NULL,
Request INT NULL
)
INSERT INTO @Table (ID, [Status], Approved, Request)
VALUES
(1, NULL, 5, NULL),
(1, 'Approved', NULL, NULL),
(1, NULL, NULL, 10)
There are a two ways to achieve this result that I am aware of:
1) Using Sub Queries in the SELECT
statement. Something like below:
SELECT T.ID,
T.[Status],
(
SELECT TOP (1) temp1.Approved
FROM @Table temp1
WHERE temp1.ID = T.ID
AND temp1.Approved IS NOT NULL
--If Needed You can add additional WHERE clauses
--Or you can add some kind of ORDER clause to get the value you want
) AS Approved,
(
SELECT TOP (1) temp1.Request
FROM @Table temp1
WHERE temp1.ID = T.ID
AND temp1.Request IS NOT NULL
--If Needed You can add additional WHERE clauses
--Or you can add some kind of ORDER clause to get the value you want
) AS Request
FROM @Table T
WHERE ID = 1
AND [Status] = 'Approved'
--If Needed You can add additional WHERE clauses
We are simply running a second and third select, selecting a single value (the TOP (1)
to avoid an error where a subquery returns more than one result), and having that display as the result for that column. The benefit of this option is it guarantees that we only get one row per instance of something in the table WHERE ID = 1 AND [Status] = 'Approved'
.
2) Another option I am aware of is using additional JOINS
. Something like below:
SELECT T.ID,
T.[Status],
App.Approved,
Req.Request
FROM @Table T
LEFT OUTER JOIN @Table App
ON App.ID = T.ID
AND App.Approved IS NOT NULL
LEFT OUTER JOIN @Table Req
ON Req.ID = T.ID
AND Req.Request IS NOT NULL
WHERE T.ID = 1
AND T.[Status] = 'Approved'
This approach allows you to get more than just a single value for that row. (Say there was some additional 5th column and you wanted that value from the "Request" row. You can just add a Req.[ColumnName]
in the SELECT
). This does have a possibility for returning multiple rows per ID = 1 AND [Status] = 'Approved'
combination, if there are more than one row with ID = 1 AND Request IS NOT NULL
OR ID = 1 and Approved IS NOT NULL
.
There is a 3rd option using the XML STUFF
:
Which allows you to combine multiple rows of the same column into a single "cell" using concatenation. This is explained in great detail via this Stack Overflow Question.
Hopefully that give you what you were looking for.
status
,approved
andrequested
but your example question has column headers likeT
,W
,X
. You haven't explained how the data might look for 4 records for same class ID - what happens if 1 record has a number in column W and another record has a different number in column W? Your rules are not clear. You're also the second person to post exactly the same example question - might this be a study assignment? What steps have you taken to try and solve the problem, so we can help you where you're stuck?