MySQL Как я могу выбрать получить определенный статус и получить последний идентификатор, если статус не соответствует требованиям?

#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
  

SEE DEMO