#mysql #sql
#mysql #sql
Вопрос:
Я видел решения для чего-то подобного в других сообщениях, но у меня возникла проблема с применением его к моей проблеме.
У меня есть эта таблица для истории ваучеров:
t_release
:
------------ --------- ---------------- -------------------
| release_id | code_id | code_status_id | code_created_date |
------------ --------- ---------------- -------------------
| 1 | 32 | 2 | 4/28/2016 8:54 |
| 1 | 32 | 2 | 4/28/2016 8:54 |
| 2 | 32 | 3 | 4/28/2016 8:55 |
| 3710 | 32 | 2 | 6/18/2016 10:20 |
| 4 | 33 | 2 | 4/28/2016 9:54 |
| 5 | 33 | 2 | 4/28/2016 10:54 |
| 3711 | 33 | 2 | 6/18/2016 11:20 |
| 6 | 34 | 2 | 4/28/2016 11:54 |
| 7 | 34 | 3 | 4/28/2016 0:54 |
| 3712 | 34 | 2 | 6/18/2016 0:20 |
------------ --------- ---------------- -------------------
И
r_code_status
:
---------------- -------------
| code_status_id | code_status |
---------------- -------------
| 1 | Available |
| 2 | Requesting |
| 3 | Paid |
---------------- -------------
Когда я запускаю:
SELECT
t1.release_id,
t1.code_id,
t1.code_status_id,
t1.code_created_date
FROM t_release t1
LEFT JOIN t_release t2 ON t1.code_id = t2.code_id AND t1.release_id < t2.release_id
WHERE ISNULL(t2.release_id)
------------ --------- ---------------- -------------------
| release_id | code_id | code_status_id | code_created_date |
------------ --------- ---------------- -------------------
| 3710 | 32 | 2 | 6/18/2016 10:20 |
| 3711 | 33 | 2 | 6/18/2016 11:20 |
| 3712 | 34 | 2 | 6/18/2016 0:20 |
------------ --------- ---------------- -------------------
Мне нужно, если code_id соответствует code_status_id = '3'
или «Оплачен», запрос может получить его как последнюю историю, иначе, если code_id
с code_status_id = '2'
последним id(release_id)
извлеченным.
Я хочу получить такой результат:
------------ --------- ---------------- -------------------
| release_id | code_id | code_status_id | code_created_date |
------------ --------- ---------------- -------------------
| 2 | 32 | 3 | 4/28/2016 08:55 |
| 3711 | 33 | 2 | 6/18/2016 11:20 |
| 7 | 34 | 3 | 4/28/2016 0:54 |
------------ --------- ---------------- -------------------
DDL:
create table t_release (
release_id INTEGER(11) NOT NULL AUTO_INCREMENT,
code_id INTEGER(11) DEFAULT NULL,
code_status_id TINYINT(4) DEFAULT NULL,
code_created_date DATETIME DEFAULT NULL,
PRIMARY KEY (`release_id`)
) ENGINE=InnoDB
AUTO_INCREMENT=1 ROW_FORMAT=DYNAMIC CHARACTER SET 'utf8';
INSERT INTO t_release
(`release_id`,`code_id`,`code_status_id`,`code_created_date`)
VALUES
(1, '32', '2', '2016-4-28 8:54'),
(2, '32', '3', '2016-4-28 8:55'),
(3710, '32', '2', '2016-6-18 10:20'),
(4, '33', '2', '2016-4-28 9:54'),
(5, '33', '2', '2016-4-28 10:54'),
(3711, '33', '2', '2016-6-18 11:20'),
(6, '34', '2', '2016-4-28 11:54'),
(7, '34', '3', '2016-4-28 0:54'),
(3712, '34', '2', '2016-6-18 0:20');
и это ссылка sqlfiddle: http://sqlfiddle.com /#!9/87843
Комментарии:
1. что такое тип
code_created_date
данных?2. тип данных code_created_date — DATETIME. я добавил DDL и ссылку sqlfiddle
3. есть ли вероятность, что несколько записей находятся
code_status_id = 3
под одним и тем жеcode_id
?4. Нет, это не так, нет шансов для нескольких записей для code_status_id = 3 с одним и тем же code_id.
5. кроме code_status_id = 2 будет иметь тот же code_id. потому что клиентское приложение может запускать запрос кнопки много раз и записывать. если оплачено, сообщение появляется в клиентском приложении и не может запрашивать снова
Ответ №1:
SELECT * FROM t_release t where release_id IN
(SELECT DISTINCT release_id FROM t_release WHERE code_status_id = 3)
UNION ALL
SELECT * FROM t_release t where release_id IN
(SELECT MAX(release_id) FROM t_release x WHERE
NOT EXISTS (SELECT 1 FROM t_release y WHERE code_status_id = 3 and y.code_id = x.code_id))
GROUP BY code_id)
Первый запрос получит все оплаченные, другой получит последний release_id из тех, которые остаются неоплаченными.
Ответ №2:
Вы можете добиться этого с помощью MySQL user defined variables
SELECT
t.release_id,
t.code_id,
t.code_status_id,
t.code_created_date
FROM
(
SELECT
*,
IF(@sameCodeID = code_id, @rn := @rn 1,
IF(@sameCodeID := code_id, @rn := 1, @rn := 1)
) AS row_number
FROM t_release t
CROSS JOIN (SELECT @sameCodeID := 0, @rn := 1) AS var
ORDER BY code_id, code_status_id DESC, release_id DESC
) AS t
WHERE t.row_number <= 1
ORDER BY t.code_id