Reputation: 2279
I am trying to write a query that would select data from multiple lines depending if there is a newer value. This has been giving me headaches for a long time already. The table is structured this way:
UniqID ProblemID DateTime Status PersonID ResponsibleID ActionID Comment Deadline PartID
15589 15589 01/16 12:11 0 25 48 12 bla1 01/16 12:11 T9865
15592 15589 01/16 12:25 1 48 48 105 bla2 null null
15601 15589 01/16 13:08 3 56 null 195 bla3 null N2654
15641 15589 01/17 18:02 3 11 23 35 null 01/18 15:00 null
15705 15589 01/18 10:24 5 23 null 255 bla4 null null
This is a mistake log and I need to perform several slightly different queries on this data.
PersonID
or as ResponsibleID
. This query would have to return
ProblemID (first)DateTime (last)Status (first)Person (last)Responsible (last)action (first)Comment (last)deadline (last)PartID
15589 01/16 12:11 5 25 23 255 bla1 01/18 15:00 N2654
PartID
T9865 was involvedI have made several attempts at this query, but the best that came out was a query that selects all stuff from the last line or the first one. I am actually struggling to figure out how to select the (last)ResponsibleID
if it is not contained in the last line. The same for other columns obviously. The only solution I can think of right now is a simple select that would return me all the rows and just filter that necessary data in a foreach loop with PHP. Because selecting different values in multiple lines is just beyond my skill :)
Thanks in advance
Upvotes: 2
Views: 2755
Reputation: 31296
TBH this probably isn't a problem for SQL to solve, but a problem for the business logic code. So whilst you will undoubtedly come up with a query that will do what you need, it may be simpler to just return all records to the client application, and have the client code deal with the problem of determining the pertinent records to display.
Upvotes: 1
Reputation: 2206
SELECT ABC.PROBLEMID,
ABC.DATETIME,--(first)DateTime
ABC.STATUS,--(last)Status
ABC.PERSON,-- (first)Person
ABC.RESPONSIBLE,-- (last)Responsible
ABC.ACTION,-- (last)action
ABC.COMMENT,-- (first)Comment
ABC.DEADLINE,-- (last)deadline
ABC.PARTID -- (last)PartID
(
SELECT TOP 1 PROBLEMID,DATETIME,PERSON,COMMENT
FROM YOURTABLE
ORDER BY DATETIME ASC
OR
SELECT TOP 1 STATUS,RESPONSIBLE,ACTION,DEADLINE,PARTID
FROM YOURTABLE
ORDER BY DATETIME DESC
) ABC
WHERE ABC.PROBLEMID IN (SELECT DISTINCT ProblemID
FROM Mistakes
WHERE PersonID = 48
OR ResponsibleID = 48)
Upvotes: 0
Reputation: 58431
The only solution I can think of is to repeat the conditions in subselects. I see no other way to get to the first/last column values that are NOT NULL
.
;WITH CurrentProblemID AS (
SELECT DISTINCT ProblemID
FROM Mistakes
WHERE PersonID = 48
OR ResponsibleID = 48
)
SELECT [ProblemID] = cpi.ProblemID
, [(first) DateTime] = (SELECT MIN(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND DateTime IS NOT NULL)
, [(last) Status] = (SELECT Status FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND Status IS NOT NULL))
, [(first) Person] = (SELECT PersonID FROM Mistakes WHERE DateTime = (SELECT MIN(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND PersonID IS NOT NULL))
, [(last) Responsible] = (SELECT ResponsibleID FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND ResponsibleID IS NOT NULL))
, [(last) Action] = (SELECT ActionID FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND ActionID IS NOT NULL))
, [(first) Comment] = (SELECT Comment FROM Mistakes WHERE DateTime = (SELECT MIN(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND Comment IS NOT NULL))
, [(last) Deadline] = (SELECT Deadline FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND Deadline IS NOT NULL))
, [(last) PartID] = (SELECT PartID FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND PartID IS NOT NULL))
FROM CurrentProblemID cpi
;WITH Mistakes AS (
SELECT *
FROM (
VALUES
(15589, 15589, '01/16 12:11', 0, 25, 48, 12, 'bla1', '01/16 12:11', 'T9865')
, (15592, 15589, '01/16 12:25', 1, 48, 48, 105, 'bla2', null, null)
, (15601, 15589, '01/16 13:08', 3, 56, null, 195, 'bla3', null, 'N2654')
, (15641, 15589, '01/17 18:02', 3, 11, 23, 35, null, '01/18 15:00', null)
, (15705, 15589, '01/18 10:24', 5, 23, null, 255, 'bla4', null, null)
) AS v (UniqID, ProblemID, DateTime, Status, PersonID, ResponsibleID, ActionID, Comment, Deadline, PartID)
)
, CurrentProblemID AS (
SELECT DISTINCT ProblemID
FROM Mistakes
WHERE PersonID = 48
OR ResponsibleID = 48
)
SELECT [ProblemID] = cpi.ProblemID
, [(first) DateTime] = (SELECT MIN(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND DateTime IS NOT NULL)
, [(last) Status] = (SELECT Status FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND Status IS NOT NULL))
, [(first) Person] = (SELECT PersonID FROM Mistakes WHERE DateTime = (SELECT MIN(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND PersonID IS NOT NULL))
, [(last) Responsible] = (SELECT ResponsibleID FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND ResponsibleID IS NOT NULL))
, [(last) Action] = (SELECT ActionID FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND ActionID IS NOT NULL))
, [(first) Comment] = (SELECT Comment FROM Mistakes WHERE DateTime = (SELECT MIN(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND Comment IS NOT NULL))
, [(last) Deadline] = (SELECT Deadline FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND Deadline IS NOT NULL))
, [(last) PartID] = (SELECT PartID FROM Mistakes WHERE DateTime = (SELECT MAX(DateTime) FROM Mistakes WHERE ProblemID = cpi.ProblemID AND PartID IS NOT NULL))
FROM CurrentProblemID cpi
Upvotes: 2