select last entry for every user multi table example - sql

Given the following tables
table message
id message time_send
14 "first" 2014-02-10 22:16:31
15 "second" 2014-02-14 09:35:20
16 "third" 2014-02-13 09:35:47
17 "fourth" 2014-03-10 22:16:31
18 "fifth" 2014-03-14 09:35:20
19 "sixth" 2014-04-12 09:35:47
20 "seventh" 2014-04-13 09:35:47
21 "eighth" 2014-04-14 09:35:47
table message_owner
id message_id owner_id cp_id
1 14 1 4
2 14 4 1
3 15 12 4
4 15 4 12
5 16 4 1
6 16 1 4
7 17 12 4
8 17 4 12
9 18 4 1
10 18 1 4
11 19 12 4
12 19 4 12
13 20 12 1
14 20 1 12
15 21 12 7
16 21 7 12
I want to query the most recent message with every counter party(cp_id) for a given owner.
For example for owner_id=4 I would like the following output:
id message time_send owner_id cp_id
18 "fifth" 2014-03-14 09:35:20 4 1
19 "sixth" 2014-02-13 09:35:47 4 12
I see a lot of examples with one table but I am not able to transpose them in a multitable example.
edit1: adding more entries

This should work:
SELECT m.id, m.message, mo.owner_id, mo.cp_id
FROM message m
JOIN message_owner mo ON m.id=mo.message_id
WHERE mo.owner_id=4
AND m.time_send=(
SELECT MAX(time_send)
FROM message m2
JOIN message_owner mo2 ON mo2.message_id=m2.id
WHERE mo2.owner_id=mo.owner_id
AND mo2.cp_id =mo.cp_id
)
... notice though that putting a WHERE condition on a timestamp column can sometimes not work correctly.
Same example without jointures:
SELECT m.id, m.time_send, m.message, mo.owner_id, mo.cp_id
FROM message m, message_owner mo
WHERE m.id = mo.message_id
AND mo.owner_id = 4
AND m.time_send = (
SELECT MAX(time_send)
FROM message m2, message_owner mo2
WHERE mo2.message_id = m2.id
AND mo2.owner_id = mo.owner_id
AND mo2.cp_id = mo.cp_id
);
http://sqlfiddle.com/#!2/558d7/4

Related

Select data based on few consideration

I wanted to select data based on the below considerations -
Now we have two tables -
TABLE 1 -
DLR_ID
CALL_ID
VEHICLE
PLAN_NO
CALL_STATUS
1
11
AA
5
Generated
2
12
AA
5
Generated
1
13
AA
10
Generated
2
14
AA
10
Not Generated
1
15
BB
5
Generated
1
16
BB
10
Generated
2
17
CC
5
Not Generated
3
18
CC
5
Generated
1
19
DD
5
Not Generated
4
20
DD
5
Not Generated
3
21
EE
5
Generated
2
22
FF
10
Generated
4
23
FF
10
Generated
5
24
GG
20
Generated
6
25
GG
20
Generated
TABLE 2 -
DLR_ID
CALL_ID
CALL_COUNT
CALL_RESULT_STATUS
CALL_DATE(DD/MM/YYYY)
1
11
1
Continue
16/03/2021
1
11
2
Give-up
20/03/2021
2
12
1
Completed
15/03/2021
1
13
1
Continue
01/04/2021
1
15
1
Completed
21/02/2021
1
16
1
Give-up
20/03/2021
3
18
1
Continue
21/05/2021
3
21
1
Give-up
24/04/2021
2
22
1
Completed
19/03/2021
4
23
1
Completed
03/05/2021
5
24
1
Continue
11/02/2021
5
24
2
Completed
11/05/2021
6
25
1
Continue
10/02/2021
6
25
2
Continue
21/02/2021
6
25
3
Continue
21/04/2021
OUTPUT -
DLR_ID
VEHICLE
PLAN_NO
CALL_STATUS
CALL_ID
CALL_DATE
CALL_RESULT_STATUS
1
AA
5
Generated
12
15/03/2021
Completed
2
AA
5
Generated
12
15/03/2021
Completed
1
AA
10
Generated
13
01/04/2021
Continue
2
AA
10
Not Generated
13
01/04/2021
Continue
1
BB
5
Generated
15
21/02/2021
Completed
1
BB
10
Generated
15
21/02/2021
Completed
2
CC
5
Not Generated
18
21/05/2021
Continue
3
CC
5
Generated
18
21/05/2021
Continue
1
DD
5
Not Generated
4
DD
5
Not Generated
3
EE
5
Generated
21
21/04/2021
Give-up
2
FF
10
Generated
23
03/05/2021
Completed
4
FF
10
Generated
23
03/05/2021
Completed
5
GG
20
Generated
24
11/05/2021
Completed
6
GG
20
Generated
24
11/05/2021
Completed
Kindly help me out in extracting the building oracle query to extract the data like mentioned in OUTPUT table.
Code which I was trying is -
SELECT t1.DLR_id, t1.VEHICLE,t1.PLAN_NO,t1.CALL_STATUS,
NVL(MAX(CASE WHEN t1.CALL_STATUS='Generated' and t2.CALL_RESULT_STATUS = 'Completed' THEN t2.CALL_ID END),
MAX(CASE WHEN t1.CALL_STATUS!='Generated' and t2.CALL_RESULT_STATUS != 'Completed' THEN t2.CALL_ID END)) as CALL_ID
FROM Table1 t1
left JOIN Table2 t2
ON t1.DLR_ID=t2.DLR_ID
and t2.call_id = t1.call_id
group by T1.DLR_ID,t1.VEHICLE,t1.PLAN_NO,
T1.CALL_STATUS
order by t1.VEHICLE,t1.plan_no,t1.dlr_id

Return running max column from another column SQL

I have a query where I would like to manipulate a column to return an array conatining only the max-value from the last 12 values from another column (due to other parts of the query).
Example:
I want to add the column MaxLast12 from:
Month Power
1 10
2 16
3 8
4 14
5 15
6 3
7 6
8 10
9 11
10 12
11 12
12 12
13 18
14 12
To become:
Month Power MaxLast12
1 10 10
2 16 16
3 8 16
4 14 16
5 15 16
6 3 16
7 6 16
8 17 17
9 11 17
10 12 17
11 12 17
12 12 17
13 18 18
14 12 18
It would also help to be able to create a simpler solution where I only include the 12 rows in the query (won't be as accurate but good enough for the purpose) with only the maximum value. Would need to do the following:
Month Power
1 6
2 6
3 8
4 14
5 15
6 3
7 6
8 10
9 11
10 12
11 12
12 12
To become:
Month Power YearMax
1 10 17
2 16 17
3 8 17
4 14 17
5 15 17
6 3 17
7 6 17
8 17 17
9 11 17
10 12 17
11 12 17
12 12 17
Since I'm guessing both problems solution will be similar, any help possible is appriciated. Would like to avoid usign GROUP BY clause since I'm modifying an existing kind of complex query.
Tried to achive this using max() with no luck.
I am using SQL-developer.
In Oracle you would use window functions:
select month, power,
max(power) over (order by month rows between 11 preceding and current row)
from t;

Compare Current Row with Previous/Next row in SQL Server

I have a table named team and it like below: I just added a row_number in the 3rd column
RaidNo OutComeID RN
2 15 1
4 15 2
6 14 3
8 16 4
10 16 5
12 14 6
14 16 7
16 15 8
18 15 9
20 16 10
22 12 11
24 16 12
26 16 13
28 16 14
30 15 15
32 14 16
34 13 17
When the OutcomeId came as 16 then start with one and 16 comes consecutively, add one by one. And the results be like
RaidNo OutComeID RN Result
2 15 1 0
4 15 2 0
6 14 3 0
8 16 4 1
10 16 5 2
12 14 6 0
14 16 7 1
16 15 8 0
18 15 9 0
20 16 10 1
22 12 11 0
24 16 12 1
26 16 13 2
28 16 14 3
30 15 15 0
32 14 16 0
34 13 17 0
Help me to get the result.
You can use the following query:
SELECT RaidNo, OutComeID, RN,
CASE
WHEN OutComeID <> 16 THEN 0
ELSE ROW_NUMBER() OVER (PARTITION BY OutComeID, grp ORDER BY RN)
END AS Result
FROM (
SELECT RaidNo, OutComeID, RN,
RN - ROW_NUMBER() OVER (PARTITION BY OutComeID ORDER BY RN) AS grp
FROM mytable) AS t
ORDER BY RN
Field grp identifies slices (also called islands) of consecutive records having the same OutComeID value. The outer query uses grp in order to enumerate each record that belongs to a '16' slice. The records that belong to the other slices are assigned value 0.
Demo here

Need assistance with a SQL query involving multiple sorts

I'm not sure if this is even possible, but my head starts to hurt when thinking about how to solve this. I've read on subqueries and PARTITION but I'm outside my knowledge. Here is a sample of my data:
TestID StudentID ComponentID Score
-------------------------------------
14919 3445 1 20
14919 3445 4 17
14919 3445 8 20
14919 3445 11 19
14919 3445 13 19
11339 3448 1 15
11339 3448 4 23
11339 3448 8 23
**11339 3448 11 22**
11339 3448 13 20
**14773 3448 1 20**
14773 3448 4 21
**14773 3448 8 23**
14773 3448 11 21
**14773 3448 13 21**
There can be multiple test attempts attached to the same StudentID. Attempts are noted by TestID.
I need to be able to query for the highest test score per TestComponentID over all attempts for each StudentID. There are only 5 component IDs. So for StudentID = 14773, between both ComponentID of 1, I just need the highest score. I would need the same for 4, 8, 11 and 13. I hope that makes sense. I highlighted the rows that would need to be returned. Any help is greatly appreciated.
Here is the query I've attempted. It just returns the same number of rows as the original.
SELECT DISTINCT
sts.StudentStandardizedTestID,
sts.StandardizedTestComponentID,
sts.StudentID,
MAX(sts.score) OVER (PARTITION BY sts.StudentID) HIGHSCORE
FROM
StandardizedTestScore sts
JOIN
StudentStandardizedTest sst ON sst.StudentStandardizedTestID = sts.StudentStandardizedTestID
AND sst.standardizedtestid = 1
WHERE
sst.TranscriptSchoolID = 10
AND sts.StandardizedTestComponentID = 1
OR sts.StandardizedTestComponentID = 4
OR sts.StandardizedTestComponentID = 8
OR sts.StandardizedTestComponentID = 11
OR sts.StandardizedTestComponentID = 13
ORDER BY
sts.studentid, sts.StandardizedTestComponentID
Below is the code to create your table and data.
CREATE TABLE StandardizedTestScore (`StudentStandardizedTestID` int(11) ,`studentid` int(11) ,`StandardizedTestComponentID` int(11),`score` int(11));
INSERT INTO StandardizedTestScore
(`TestID`, `studentid`, `componentid`, `score`)
VALUES
(14919,3445,1,20),
(14919,3445,4,17),
(14919,3445,8,20),
(14919,3445,11,19),
(14919,3445,13,19),
(11339,3448,1,15),
(11339,3448,4,23),
(11339,3448,8,23),
(11339,3448,11,22),
(11339,3448,13,20),
(14773,3448,1,20),
(14773,3448,4,21),
(14773,3448,8,23),
(14773,3448,11,21),
(14773,3448,13,21);
The query you are looking for is this..
SELECT studentid,StandardizedTestComponentID as componentID,MAX(score) AS score
FROM StandardizedTestScore
GROUP BY studentid,StandardizedTestComponentID
The results are this..
studentid ComponentID Score
3445 1 20
3445 4 17
3445 8 20
3445 11 19
3445 13 19
3448 1 20
3448 4 23
3448 8 23
3448 11 22
3448 13 21
It sounds to me like you need aggregation not sorting. Something like:
SELECT studentid,testid,componentid,MAX(score) AS score
FROM yourtable
GROUP BY studentid,testid,componentid

Select sum of condition

I have a table like below. I want to select some rows that sum of cnt<120. how to do this?
cnt id
_________
6 14001
17 14005
14 14017
16 14024
9 14025
7 14027
10 14029
14 14048
23 14055
18 14056
19 14058
18 14059
18 14063
15 14064
9 14086
17 14095
9 14098
14 14116
10 14138
8 14147
17 14165
22 14171
22 14191
18 14194
13 14204
17 14221
13 14245
14 14249
6 14254
17 14257
9 14260
19 14261
26 14263
6 14264
27 14265
19 14269
11 14287
SELECT SUM(cnt)
FROM my_table
WHERE cnt < 120
You can try this:-
SELECT *
FROM test O
HAVING (SELECT sum(cnt) FROM test WHERE cnt <= O.cnt) <120