Объединить MySQL операторы SELECT - PullRequest
0 голосов
/ 10 февраля 2020

У меня есть следующая таблица tbl_crps , обратите внимание, что столбец crp встречается более одного раза, но id и start_on будут всегда отличаются в записях с одинаковыми crp .

id |  crp | starts_on  |
------------------
1  |  20  | 2020-02-09 |
2  |  31  | 2019-06-05 |
3  |  20  | 2018-01-10 |
4  |  31  | 2021-07-03 |
5  |  58  | 2022-01-01 |
6  |  58  | 2025-02-02 |

Мне нужно извлечь записи со следующими условиями:

  1. Если для crp существует одна или несколько записей с прошлыми start_on , затем должна быть возвращена запись с наибольшим идентификатором среди этих записей с этими crp (записи с прошлой датой)

  2. Если для crp записей с прошедшей датой не существует, то запись с наибольшим идентификатором среди всех записей с этим crp

Я могу успешно выбрать записи, соответствующие первому условию со следующим.

SELECT * FROM tbl_crps AND id IN (SELECT MAX(b.id) FROM tbl_crps b WHERE b.starts_on <= "2020-10-02")

Вернет записи с идентификаторами 3 и 2.

Чего мне нужно добиться, так это добавить к результату те записи, которых start_on нет в прошлом и hich crp не в первом наборе результатов.

Возможно ли это? Может быть, так?

SELECT * FROM tbl_crps a
WHERE id IN (
     SELECT MAX(a.id) FROM tbl_crps a WHERE a.starts_on <= "2020-10-02" GROUP BY a.crp
 )
UNION
(
    SELECT * FROM tbl_crps b
        WHERE id IN (
             SELECT MAX(c.id) FROM tbl_crps c WHERE c.starts_on > "2020-10-02"
             AND c.crp NOT IN (
                  SELECT d.crp FROM tbl_crps d
                  WHERE id IN (
                       SELECT MAX(e.id) FROM tbl_crps e WHERE e.starts_on <= "2020-10-02" GROUP BY e.crp)
                   )
        )
)

Я использую MySQL 5.7

Ответы [ 2 ]

1 голос
/ 11 февраля 2020

Я не уверен, что полностью понимаю ваши требования, но я думаю, что этот запрос выполняет то, что вы ищете, или очень близок к нему:

WITH cteData AS (SELECT b.CRP, MAX(b.ID) AS ID
                   FROM tbl_crps b
                   WHERE b.starts_on <= "2020-10-02"
                   GROUP BY b.CRP)
SELECT *
  FROM tbl_crps a
  WHERE a.ID IN (SELECT ID
                   FROM (SELECT b.CRP, b.ID
                           FROM cteData b
                         UNION
                         SELECT d.CRP, d.ID
                           FROM tbl_crps d
                           WHERE d.starts_on > "2020-10-02" AND
                                 d.CRP NOT IN (SELECT crp
                                                 FROM cteData)) c)

Это возвращает

id  crp starts_on
2   31  2019-06-05
3   20  2018-01-10
5   58  2022-01-01
6   58  2025-02-02

, что кажется правильным на основании моего понимания требований. Короче говоря

1 - NOT included because its date is in the past ('current' date = 2020-10-02) 
    and its ID is NOT the greatest among records in the past with that CRP.
2 - included because its date is in the past and its ID is the greatest
    among records with that CRP which have dates in the past.
3 - date is in the past, ID is greatest for that CRP with date in the past
4 - NOT included because date is in the future, but CRP is included in recs
    from first subquery.
5 - date is in the future, and CRP does not occur in first subquery
6 - date is in the future, and CRP does not occur in first subquery

дБ <> скрипка здесь

0 голосов
/ 11 февраля 2020

Начиная с ответа Акины на мой новый вопрос (он был закрыт), это делает работу.

{ ссылка }

SELECT id, crp, starts_on
FROM tbl_crps
NATURAL JOIN (SELECT crp, MAX(id) id
              FROM tbl_crps
              WHERE starts_on < CURRENT_DATE
              GROUP BY crp) x
UNION ALL
SELECT id, crp, starts_on
FROM tbl_crps
NATURAL JOIN (SELECT crp, MAX(id) id
              FROM tbl_crps
              GROUP BY crp
              HAVING MIN(starts_on) >= CURRENT_DATE) x;

скрипка

Мое решение (не работает)

SELECT * FROM tbl_crps a
WHERE id IN (
     SELECT MAX(a.id) FROM tbl_crps a WHERE a.starts_on <= "2020-10-02"
 )
UNION
(
    SELECT * FROM tbl_crps b
        WHERE id IN (
             SELECT MAX(c.id) FROM tbl_crps c WHERE c.starts_on > "2020-10-02"
             AND c.crp NOT IN (
                  SELECT d.crp FROM tbl_crps d
                  WHERE id IN (
                       SELECT MAX(e.id) FROM tbl_crps e WHERE e.starts_on <= "2020-10-02")
                   )
        )
)
...