I have the following table
+--------+-----------+---------+----------------------------+---------------------+--------------------+
| msg_id | user_from | user_to | msg_text | msg_time | msg_read |
+--------+-----------+---------+----------------------------+---------------------+--------------------+
| 1 | 1 | 72 | Hello Mark from Andy | 2014-09-18 12:44:09 | 2014-09-20 12:44:09|
| 2 | 72 | 1 | Hello Andy from Mark | 2014-09-22 12:45:26 | 2014-09-28 12:45:26|
| 3 | 1 | 72 | Back to you Mark from Andy | 2014-10-18 12:46:01 | |
| 4 | 12388 | 1 | Hello Andy from Graham | 2014-09-20 12:45:37 | 2014-09-20 12:46:37|
| 5 | 1 | 12388 | Hello Graham from Andy | 2014-09-20 12:51:08 | |
| 6 | 106 | 1 | Hello Andy from Carol | 2015-04-18 12:47:04 | |
+--------+-----------+---------+----------------------------+---------------------+--------------------+
As SQLFiddle is down at the moment, here is the query.
-- ----------------------------
-- Table structure for `messages`
-- ----------------------------
DROP TABLE IF EXISTS `messages`;
CREATE TABLE `messages` (
`msg_id` int(11) NOT NULL AUTO_INCREMENT,
`user_from` int(11) NOT NULL,
`user_to` int(11) NOT NULL,
`msg_text` text,
`msg_time` datetime DEFAULT NULL,
`msg_read` datetime DEFAULT NULL,
PRIMARY KEY (`msg_id`),
KEY `IX_MESSAGES` (`user_from`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of messages
-- ----------------------------
INSERT INTO `messages` VALUES ('1', '1', '72', 'Hello Mark from Andy', '2014-09-18 12:44:09', '2014-09-20 12:44:09');
INSERT INTO `messages` VALUES ('2', '72', '1', 'Hello Andy from Mark', '2014-09-22 12:45:26', '2014-09-28 12:45:26');
INSERT INTO `messages` VALUES ('3', '1', '72', 'Back to you Mark from Andy', '2014-10-18 12:46:01', null);
INSERT INTO `messages` VALUES ('4', '12388', '1', 'Hello Andy from Graham', '2014-09-20 12:45:37', '2014-09-20 12:46:37');
INSERT INTO `messages` VALUES ('5', '1', '12388', 'Hello Graham from Andy', '2014-09-20 12:51:08', null);
INSERT INTO `messages` VALUES ('6', '106', '1', 'Hello Andy from Carol', '2015-04-18 12:47:04', null);
As you may have guessed, this is a for a messaging system. In order to show in a Facebook style inbox, I want to extract a result set that shows the distinct users that a specific user has had communication with but I also want to include the latest message along with the message time and whether it was read, bearing in mind the latest message could either be from the sender or the recipient.
Getting the distinct users was easy enough. I simply use a UNION as follows:
SELECT
t.user_id,
t.msg_read,
t.msg_time,
t.msg_text
FROM
(
(
SELECT
m.user_from AS user_id,
m.msg_time,
m.msg_text,
m.msg_read
FROM
messages m
WHERE
m.user_to = 1
)
UNION
(
SELECT
m.user_to AS user_id,
m.msg_time AS msg_time,
m.msg_text,
m.msg_read
FROM
messages m
WHERE
m.user_from = 1
)
) t
GROUP BY user_id
This produces:
+---------+--------------------+---------------------+------------------------+
| user_id | msg_read | msg_time | msg_text |
+---------+--------------------+---------------------+------------------------+
| 72 | 2014-09-28 12:45:26| 2014-09-22 12:45:26 | Hello Andy from Mark |
| 106 | | 2015-04-18 12:47:04 | Hello Andy from Carol |
| 12388 | 2014-09-20 12:46:37| 2014-09-20 12:45:37 | Hello Andy from Graham |
+---------+--------------------+---------------------+------------------------+
Getting the latest message though is proving tricky. In the past I have simply used a JOIN to another subquery, but when trying to do the same with this, it (of course) doesn't recognise the t table.
SELECT
t.user_id,
t.msg_read,
t.msg_time AS msg_time,
t.msg_text
FROM
(
(
SELECT
m.user_from AS user_id,
m.msg_time AS msg_time,
m.msg_text,
m.msg_read
FROM
messages m
WHERE
m.user_to = 1
)
UNION
(
SELECT
m.user_to AS user_id,
m.msg_time AS msg_time,
m.msg_text,
m.msg_read
FROM
messages m
WHERE
m.user_from = 1
)
) t
INNER JOIN (SELECT MAX(msg_time) AS msg_time, user_id FROM t GROUP BY user_id) t2 ON (t.user_id=t2.user_id AND t.msg_time=t2.msg_time)
GROUP BY user_id
Table 't' doesn't exist
I realise that I could simply JOIN to another query containing the UNION but this seems a rather inefficient way of working.
I also hoped that I could create a temporary table, however it seems this is forbidden by the hosting provider.
Does anyone have any suggestions? I am happy to consider alternatives to the UNION concept.
For reference, the expected outcome should be:
+---------+--------------------+---------------------+----------------------------+
| user_id | msg_read | msg_time | msg_text |
+---------+--------------------+---------------------+----------------------------+
| 106 | | 2015-04-18 12:47:04 | Hello Andy from Carol |
| 72 | | 2014-10-18 12:46:01 | Back to you Mark from Andy |
| 12388 | 2014-09-20 12:46:37| 2014-09-20 12:51:08 | Hello Graham from Andy |
+---------+--------------------+---------------------+----------------------------+
First, you don't need the union. This following query gets all messages:
SELECT (case when m.user_to = 1 then m.user_from else m.user_to end) AS user_id,
m.msg_time, m.msg_text, m.msg_read
FROM messages m
WHERE 1 in (m.user_to, m.user_from);
If you want the most recent one for each user, just use aggregation to get the most recent message and use a join for filtering:
SELECT m.*
FROM (SELECT (case when m.user_to = 1 then m.user_from else m.user_to end) AS user_id,
m.msg_time, m.msg_text, m.msg_read
FROM messages m
WHERE 1 in (m.user_to, m.user_from)
) m JOIN
(SELECT (case when m.user_to = 1 then m.user_from else m.user_to end) AS user_id,
MAX(m.msg_time) as maxt
FROM messages m
WHERE 1 in (m.user_to, m.user_from)
GROUP BY (case when m.user_to = 1 then m.user_from else m.user_to end)
) mm
ON m.user_id = mm.user_id and
m.msg_time = mm.maxt;
Related
I'm working on the following user table, where role = 2 means the user is an instructor, and role = 3 means that the user is a student.
+--------+------+---------------+
| name | role | creation_date |
+--------+------+---------------+
| Tom | 2 | 2020-07-01 |
| Diana | 3 | 2020-07-01 |
| Rachel | 3 | 2020-07-01 |
| Michel | 3 | 2020-08-01 |
+--------+------+---------------+
My goal is to select the sum value of all instructors and students, grouped by date. The result should look like this:
+------------------+---------------+---------------+
| totalInstructors | totalStudents | creation_date |
+------------------+---------------+---------------+
| 1 | 2 | 2020-07-01 |
| 0 | 1 | 2020-08-01 |
+------------------+---------------+---------------+
In this case, on 2020-07-01, I had 1 instructor and 2 students registered and on 2020-08-01, I had no instructors and I had 1 student registered.
My problem is that I am having difficulties in setting up this query, if someone can help me thank you very much!
You would need count with a case statement as follows
select count(case when role=2 then 1 end) as totalInstructors
,count(case when role=3 then 1 end) as totalStudents
,creation_date
from tbl
group by creation_date
Use conditional aggregation:
SELECT
creation_date,
COUNT(CASE WHEN role = 2 THEN 1 END) AS totalInstructors,
COUNT(CASE WHEN role = 3 THEN 1 END) AS totalStudents
FROM yourTable
GROUP BY
creation_date;
Demo
A simple GRoupBY and SUM helps
This works. because the compasison role = 2 gives 1 back it it tue and 0 if it is false
CREATE TABLE table1 (
`name` VARCHAR(6),
`role` INTEGER,
`creation_date` VARCHAR(10)
);
INSERT INTO table1
(`name`, `role`, `creation_date`)
VALUES
('Tom', '2', '2020-07-01'),
('Diana', '3', '2020-07-01'),
('Rachel', '3', '2020-07-01'),
('Michel', '3', '2020-08-01');
SELECT
SUM(`role` = 2) totalInstructors ,
SUM(`role` = 3) totalStudents,
`creation_date`
FROM table1
GROUP BY `creation_date`
ORDER BY `creation_date`
totalInstructors | totalStudents | creation_date
---------------: | ------------: | :------------
1 | 2 | 2020-07-01
0 | 1 | 2020-08-01
db<>fiddle here
Please use below query,
select
case when role = 2 then count(1) end as totalInstructors,
case when role = 3 then count(1) end as totalStudents,
creation_date
from table_name
group by creation_date;
You can use COALESCE() to replace null with 0
select COALESCE(totalInstructors, 0) as totalInstructors, COALESCE(totalStudents, 0) as totalStudents,creation_date
from
(select
case when role = 2 then count(1) end as totalInstructors,
case when role = 3 then count(1) end as totalStudents,
creation_date
from table_name
group by creation_date) qry;
Using MySQL, I want to select all submissions (rows) which last submission is NULL and previous one is not, grouped by user_id.
If I consider the following example table, then the answer would be rows: 2, 5 and 7.
| ID | submission | date_submission | user_id |
|----|------------|-----------------|---------|
| 1 | lorem | 2019-01-01 | 1 |
| 2 | ipsum | 2019-01-02 | 1 |
| 3 | NULL | 2019-01-03 | 1 |
| 4 | amet | 2019-01-05 | 2 |
| 5 | NULL | 2019-01-06 | 2 |
| 6 | sit | 2019-01-04 | 1 |
| 7 | sed | 2019-01-08 | 3 |
| 8 | elit | 2019-01-07 | 4 |
| 9 | NULL | 2019-01-09 | 3 |
MRE:
CREATE TABLE submissions (
id int NOT NULL,
submission varchar(45) NULL,
date_submitted date NOT NULL,
user_id int DEFAULT NULL
);
insert into submissions (1, "lorem", 2019-01-01, 1);
insert into submissions (2, "ipsum", 2019-01-02, 1);
insert into submissions (3, NULL, 2019-01-03, 1);
insert into submissions (4, "amet", 2019-01-05, 2);
insert into submissions (5, NULL, 2019-01-06, 2);
insert into submissions (6, "sit", 2019-01-04, 1);
insert into submissions (7, "sed", 2019-01-08, 3);
insert into submissions (8, "elit", 2019-01-07, 4);
insert into submissions (9, NULL, 2019-01-09, 3);
First get the last date with null submission for each user and then join to the table to get the rows of the previous dates.
By using ROW_NUMBER() get the last of these previous dates if it is not null:
select t.id, t.submission, t.date_submitted, t.user_id
from (
select s.*,
row_number() over (partition by s.user_id order by s.date_submitted desc) rn
from submissions s inner join (
select user_id,
max(case when submission is null then date_submitted end) maxnulldate
from submissions
group by user_id
) g on g.user_id = s.user_id and g.maxnulldate > s.date_submitted
) t
where t.rn = 1 and t.date_submitted is not null
See the demo.
Results:
| id | submission | date_submitted | user_id |
| --- | ---------- | -------------- | ------- |
| 2 | ipsum | 2019-01-02 | 1 |
| 4 | amet | 2019-01-05 | 2 |
| 7 | sed | 2019-01-08 | 3 |
I guess you meant row number 4 and not 5 in your expected results, right?
You can use lag() for this:
select s.*
from (select s.*,
lag(submission) over (partition by user_id order by date_submitted) as prev_submission
from submissions s
) s
where prev_submission is not null and submission is null;
Here is a db<>fiddle.
EDIT:
It occurs to me that "last submission" really is the last submission for each user. In that case, the above can be tweaked:
select s.*
from (select s.*,
row_number() over (partition by user_id order by date_submitted desc) as seqnum,
lag(submission) over (partition by user_id order by date_submitted) as prev_submission
from submissions s
) s
where prev_submission is not null and submission is null and seqnum = 1;
I need to get all DISTINCT users excluding those who are not available according to unavailability periods of time.
The user table:
+------+-----------+--------------------------------------+
| id | firstname | content |
+------+-----------+--------------------------------------+
| 13 | John | ... |
| 44 | Marc | ... |
| 55 | Elise | ... |
+------+-----------+--------------------------------------+
The unavailability periods table:
+------+-----------+--------------+--------------+
| id | user_id | start | end |
+------+-----------+--------------+--------------+
| 1 | 13 | 2019-07-01 | 2019-07-10 |
| 2 | 13 | 2019-07-20 | 2019-07-30 |
| 3 | 13 | 2019-09-01 | 2019-09-30 |
| 4 | 44 | 2019-08-01 | 2019-08-15 |
+------+-----------+--------------+--------------|
For example, we want user who are available from 2019-06-20 to 2019-07-05: Marc and Elise are available.
Do I have to use a LEFT JOIN? This request is not working:
SELECT DISTINCT user.*, unavailability.start, unavailability.end,
FROM user
LEFT JOIN unavailability ON unavailability.user_id = user.id
WHERE
unavailability.start < "2019-06-20" AND unavailability.end > "2019-06-20"
AND unavailability.start < "2019-07-05" AND unavailability.end > "2019-07-05"
And I need as result:
+------+-----------+--------------------------------------+
| id | firstname | content |
+------+-----------+--------------------------------------+
| 44 | Marc | ... |
| 55 | Elise | ... |
+------+-----------+--------------------------------------+
With this request I don't get Elise who has no unavailability periods of time.
DROP TABLE IF EXISTS user;
CREATE TABLE user
(id SERIAL PRIMARY KEY
,firstname VARCHAR(12) NOT NULL UNIQUE
);
INSERT INTO user VALUES
(13,'John'),
(44,'Marc'),
(55,'Elise');
DROP TABLE IF EXISTS unavailability ;
CREATE TABLE unavailability
(id SERIAL PRIMARY KEY
,user_id INT NOT NULL
,start DATE NOT NULL
,end DATE NOT NULL
);
INSERT INTO unavailability VALUES
(1,13,'2019-07-01','2019-07-10'),
(2,13,'2019-07-20','2019-07-30'),
(3,13,'2019-09-01','2019-09-30'),
(4,44,'2019-08-01','2019-08-15');
SELECT x.*
FROM user x
LEFT
JOIN unavailability y
ON y.user_id = x.id
AND y.start <= '2019-07-05'
AND y.end >= '2019-06-20'
WHERE y.id IS NULL;
+----+-----------+
| id | firstname |
+----+-----------+
| 44 | Marc |
| 55 | Elise |
+----+-----------+
2 rows in set (0.01 sec)
This approach can be used:
select * from user k
where not exists (
select 1 from user
join unavailability u on u.user_id = user.id
and ('2019-06-20' between start and end or '2019-07-05' between start and end)
where user.id = k.id)
You can select the ids of the unavailables and use this result in a subquery :
Schema (MySQL v5.7)
CREATE TABLE user (
`id` INTEGER,
`firstname` VARCHAR(5),
`content` VARCHAR(3)
);
INSERT INTO user
(`id`, `firstname`, `content`)
VALUES
(13, 'John', '...'),
(44, 'Marc', '...'),
(55, 'Elise', '...');
CREATE TABLE unavailability (
`id` INTEGER,
`user_id` INTEGER,
`start` DATETIME,
`end` DATETIME
);
INSERT INTO unavailability
(`id`, `user_id`, `start`, `end`)
VALUES
(1, 13, '2019-07-01', '2019-07-10'),
(2, 13, '2019-07-20', '2019-07-30'),
(3, 13, '2019-09-01', '2019-09-30'),
(4, 44, '2019-08-01', '2019-08-15');
Query #1
SELECT *
FROM user us
WHERE us.id NOT IN (
SELECT u.user_id
FROM unavailability u
WHERE u.start <= '2019-07-05' AND u.end >= '2019-06-20'
);
| id | firstname | content |
| --- | --------- | ------- |
| 44 | Marc | ... |
| 55 | Elise | ... |
View on DB Fiddle
Note
This condition :
unavailability.start < 2019-06-20 AND unavailability.end > 2019-06-20
AND unavailability.start < 2019-07-05 AND unavailability.end > 2019-07-05
Will be evaluated like this :
unavailability.start < 2019-06-20 AND unavailability.end > 2019-07-05
Because, for the parts unavailability.start < 2019-06-20 AND unavailability.start < 2019-07-05, everything below 2019-07-05 but above 2019-06-20 will be excluded (you are using AND). The same for both unavailability.end
I have two tables as mentioned below.
user table
id | username | password | status |
1 | Prajna | ***** | active |
2 | Akshata | ***** | active |
3 | Sanjana | ***** | inactive |
test table
id | project_name | created_by (user id) | edited_by (user id) |
1 | Test | 1 | 2 |
2 | Trial | 1 | 1 |
3 | Pro1 | 2 | 2 |
I am trying with below query.
select project_name, user.username from test join user on user.id=test.created_by where user.status='active';
I wanted the result like below
I want to retrieve the result as below
How can I retrieve?
project_name | username(created by) | username (edited by) |
Test | Prajna | Akshata |
Trial | Prajna | Prajna |
Pro1 | Akshata | Akshata |
Try this code.
create table `user`
(
`id` int,
`username` varchar(20),
`password` varchar(20),
`status` varchar(20)
)
insert into `user` (`id`,`username`,`password`,`status`) values
(1, 'Prajna', '*****', 'active'),
(2, 'Akshata', '*****', 'active'),
(3, 'Sanjana', '*****', 'inactive')
create table `test`
(
`id` int,
`project_name` varchar(20),
`created_by` int,
`edited_by` int
)
insert into `test` (`id`,`project_name`,`created_by`,`edited_by`) values
(1, 'Test', 1, 2),
(2, 'Trial', 1, 1),
(3, 'Pro1', 2, 2)
SELECT
`t`.`project_name`,
`ua`.`username` as 'username (created by)' ,
`ub`.`username` as 'username (edited by)'
FROM `test` `t`
JOIN `user` `ua` ON `t`.`created_by` = `ua`.`id`
JOIN `user` `ub` ON `t`.`edited_by` = `ub`.`id`
WHERE
`ua`.`status` = 'active'
AND `ub`.`status` = 'active'
order by `t`.`id`
project_name | username (created by) | username (edited by)
:----------- | :-------------------- | :-------------------
Test | Prajna | Akshata
Trial | Prajna | Prajna
Pro1 | Akshata | Akshata
db<>fiddle here
SELECT
test.project_name, user.username
FROM test
INNER JOIN user
ON user.id = test.created_by
WHERE user.status='active';
PS: you have an error here user.id=test=created_by
.
You need sub-query and join between those two sub-query using join
select project_name,created_by,edited_by from
(
select u.id,project_name, u.username as created_by from user u left join test t1 on
u.id= t1.created_by
where user.status='active'
) Table1
inner join
(
select u.id,project_name, u.username as edited_by from user u left join test t2 on
u.id= t2.created_by
where user.status='active'
) table2 on Table1.project_name=table2.project_name
I'm working in HeidiSQL and I'm trying to figure out how to delete all duplicate rows except for the most recent. There are some slight differences amongst the "duplicates," but whenever more than four specific values are identical (i.e. UserID, ContactID, SMSID, and EventID) the row is considered a duplicate. I need to remove these according to the most recent row (identified by CreatedDate).
The following query identifies these rows:
SELECT a.UserID, a.ContactID, a.SMSID, a.EventID, CreatedDate
FROM WhenToText a
JOIN (SELECT UserID, ContactID, SMSID, EventID
FROM WhenToText
GROUP BY UserID, ContactID, SMSID, EventID
HAVING COUNT(*) > 1 ) b
ON a.UserID = b.UserID
AND a.ContactID = b.ContactID
AND a.SMSID = b.SMSID
AND a.EventID = b.EventID
ORDER BY UserID, ContactID, SMSID, EventID, CreatedDate DESC
However, I'm not sure how to delete these duplicates after I've identified them.
Here is some sample data:
Here is one approach:
DELETE FROM WhenToText w1
INNER JOIN
(
SELECT UserID, ContactID, SMSID, EventID, MAX(CreatedDate) AS MaxDate
FROM WhenToText
GROUP BY UserID, ContactID, SMSID, EventID
) w2
ON w1.UserID = w2.UserID AND w1.ContactID = w2.ContactID AND w1.SMSID = w2.SMSID
AND w1.EventID = w2.EventID
AND w1.CreatedDate != w2.MaxDate
This will delete any record for a given (UserID, ContactID, SMSID, EventID) group whose CreatedDate is not the most recent. Keep in mind this may leave behind more than one record for each group in the event that the latest CreatedDate is shared.
If you want to test which this query first to see which records will be targeted for deletion, you can replace DELETE FROM WhenToText w1 with SELECT w1.* FROM WhenToText w1.
Here is a link to a SQL Fiddle which demonstrates how the query will identify records for deletion:
SQLFiddle
Here is a solution using DELETE FROM JOIN, w/ a full demo with your data.
SQL:
-- Data preparation
create table WhenToText(UserID int, ContactID int, SMSID int, EventID int, CreatedDate datetime);
insert into WhenToText values
(4, 25, 7934, 7407, '2016-02-10 00:00:11'),
(4, 25, 7934, 7407, '2016-02-09 00:00:12'),
(4, 29, 5132, 7407, '2016-02-10 00:00:11'),
(4, 29, 5132, 7407, '2016-02-09 00:00:12'),
(4, 31, 12944, 7405, '2016-02-10 07:03:02'),
(4, 31, 12944, 7405, '2016-02-10 05:03:02'),
(4, 146, 12908, 7405, '2016-02-10 06:52:02'),
(4, 146, 12908, 7405, '2016-02-10 04:52:02'),
(15, 63, 12964, 7401, '2016-02-10 03:42:04'),
(15, 63, 12964, 7401, '2016-02-10 03:41:04'),
(15, 64, 12326, 7401, '2016-02-07 03:01:03'),
(15, 64, 12326, 7401, '2016-02-07 03:00:03');
SELECT * FROM WhenToText;
-- SQL needed
DELETE a FROM
WhenToText a INNER JOIN
(
SELECT UserID, ContactID, SMSID, EventID, MAX(CreatedDate) CreatedDate
FROM WhenToText
GROUP BY UserID, ContactID, SMSID, EventID
) b
USING(UserID, ContactID, SMSID, EventID)
WHERE
a.CreatedDate != b.CreatedDate;
SELECT * FROM WhenToText;
Output:
mysql> SELECT * FROM WhenToText;
+--------+-----------+-------+---------+---------------------+
| UserID | ContactID | SMSID | EventID | CreatedDate |
+--------+-----------+-------+---------+---------------------+
| 4 | 25 | 7934 | 7407 | 2016-02-10 00:00:11 |
| 4 | 25 | 7934 | 7407 | 2016-02-09 00:00:12 |
| 4 | 29 | 5132 | 7407 | 2016-02-10 00:00:11 |
| 4 | 29 | 5132 | 7407 | 2016-02-09 00:00:12 |
| 4 | 31 | 12944 | 7405 | 2016-02-10 07:03:02 |
| 4 | 31 | 12944 | 7405 | 2016-02-10 05:03:02 |
| 4 | 146 | 12908 | 7405 | 2016-02-10 06:52:02 |
| 4 | 146 | 12908 | 7405 | 2016-02-10 04:52:02 |
| 15 | 63 | 12964 | 7401 | 2016-02-10 03:42:04 |
| 15 | 63 | 12964 | 7401 | 2016-02-10 03:41:04 |
| 15 | 64 | 12326 | 7401 | 2016-02-07 03:01:03 |
| 15 | 64 | 12326 | 7401 | 2016-02-07 03:00:03 |
+--------+-----------+-------+---------+---------------------+
12 rows in set (0.00 sec)
mysql>
mysql> -- SQL needed
mysql> DELETE a FROM
-> WhenToText a INNER JOIN
-> (
-> SELECT UserID, ContactID, SMSID, EventID, MAX(CreatedDate) CreatedDate
-> FROM WhenToText
-> GROUP BY UserID, ContactID, SMSID, EventID
-> ) b
-> USING(UserID, ContactID, SMSID, EventID)
-> WHERE
-> a.CreatedDate != b.CreatedDate;
SELECT * FQuery OK, 6 rows affected (0.00 sec)
mysql>
mysql> SELECT * FROM WhenToText;
+--------+-----------+-------+---------+---------------------+
| UserID | ContactID | SMSID | EventID | CreatedDate |
+--------+-----------+-------+---------+---------------------+
| 4 | 25 | 7934 | 7407 | 2016-02-10 00:00:11 |
| 4 | 29 | 5132 | 7407 | 2016-02-10 00:00:11 |
| 4 | 31 | 12944 | 7405 | 2016-02-10 07:03:02 |
| 4 | 146 | 12908 | 7405 | 2016-02-10 06:52:02 |
| 15 | 63 | 12964 | 7401 | 2016-02-10 03:42:04 |
| 15 | 64 | 12326 | 7401 | 2016-02-07 03:01:03 |
+--------+-----------+-------+---------+---------------------+
6 rows in set (0.00 sec)
This should provide the solution you're looking for, given CreatedDate is a date datatype. This is also under the assumption that the most recent row is technically the most recent CreatedDate.
SELECT UserID, ContactID, SMSID, EventID, MAX(CreatedDate) AS CreatedDate
FROM WhenToText
GROUP BY 1, 2, 3, 4;
With these values you could just overwrite WhenToText table...which would look something like this...
CREATE TABLE tmp_table LIKE WhenToText;
INSERT INTO tmp_table (SELECT UserID, ContactID, SMSID, EventID, MAX(CreatedDate) AS CreatedDate
FROM WhenToText
GROUP BY 1, 2, 3, 4);
TRUNCATE WhenToText;
INSERT INTO WhenToText (SELECT * FROM tmp_table);
DROP TABLE tmp_table;