Написание Query для получения первого значения без top, fetch, limit - PullRequest
0 голосов
/ 16 мая 2018

Для проекта мне нужно написать запрос на SQL (на PostgreSQL), который возвращает первого художника, чья смерть наступила после художника по имени «Луи Армстронг».В запросе я не могу использовать FETCH, TOP, ROWNUM, LIMIT.

Это мои таблицы

   ARTIST
   ID(PK)
   GID(PK)
   NAME(PK)
   SORT_NAME(PK)
   BEGIN_DATE_YEAR
   BEGIN_DATE_MONTH
   BEGIN_DATE_DAY
   TYPE(FK) --(TYPE NUMBER)

   ARTIST_TYPE
   ID(PK)
   NAME(PK)--(PERSON,GROUP,OTHER)

Это запрос, который я записал, правильный, но я не могу использоватьпредложение LIMIT

   SELECT A.NAME, 
   CONCAT_WS('/',A.BEGIN_DATE_DAY::text,A.BEGIN_DATE_MONTH::text,
   A.BEGIN_DATE_YEAR::text) AS DATA_NASCITA,
   CONCAT_WS('/',A.END_DATE_DAY::text,A.END_DATE_MONTH::text,
   A.END_DATE_YEAR::text) AS DATA_MORTE
   FROM artist AS A
   JOIN artist_type AS AT ON A.TYPE = AT.ID
   WHERE AT.NAME LIKE 'Per%' AND A.END_DATE_YEAR > ALL 
                (SELECT A.END_DATE_YEAR FROM artist AS A
                 JOIN artist_type AS AT ON A.TYPE = AT.ID
                 WHERE AT.NAME LIKE 'Per%' AND A.END_DATE_YEAR <= ALL
                     (
                         SELECT A.END_DATE_YEAR FROM artist AS A
                         JOIN artist_type AS AT ON A.TYPE = AT.ID
                         WHERE AT.NAME LIKE 'Per%' AND A.NAME LIKE 'Lou%'
                     )
                 )
           ORDER BY A.END_DATE_YEAR ASC
           LIMIT 1

Ответы [ 3 ]

0 голосов
/ 16 мая 2018

Я полагаю, вам запрещено использовать FETCH, TOP, ROWNUM, LIMIT.
Так что это просто вопрос используемой логики, попробуйте воспроизвести этот псевдокод:

select *
from artists a
where a.deathDate > (select deatheDate from artists where name = 'Louis Armstrong')
    and not exists (
        select 1
        from artists b
        where b.deathDate < a.deathDate
)

Внимание! Может быть более одного, соответствующего вашим критериям.

0 голосов
/ 16 мая 2018

То, что, как я полагаю, вы намеревались написать ...

WITH
  artist_per AS
(
  SELECT *
    FROM artist        AS A
    JOIN artist_type   AS AT   ON AT.ID = A.TYPE
   WHERE AT.name LIKE 'Per%'
)
SELECT
  NAME,
  CONCAT_WS('/',BEGIN_DATE_DAY::text,BEGIN_DATE_MONTH::text,BEGIN_DATE_YEAR::text) AS DATA_NASCITA,
  CONCAT_WS('/',  END_DATE_DAY::text,  END_DATE_MONTH::text,  END_DATE_YEAR::text) AS DATA_MORTE
FROM
  artist_per
WHERE
  END_DATE = (
              SELECT MIN(END_DATE)
                FROM artist_per
               WHERE END_DATE > (
                                 SELECT MIN(END_DATE)
                                   FROM artist_per
                                  WHERE NAME LIKE 'Lou%'
                                )
             )

Вернет одну строку, если только один человек умер в день сразу после смерти Lou%.

0 голосов
/ 16 мая 2018

Если вы хотите сделать сложный и медленный код, вы можете попробовать это ...

SELECT DISTINCT

  FIRST_VALUE(
    A.NAME
  ) OVER END_DATE_YEAR_ASC
                               AS NAME,
  FIRST_VALUE(
    CONCAT_WS('/',A.BEGIN_DATE_DAY::text,A.BEGIN_DATE_MONTH::text,A.BEGIN_DATE_YEAR::text)
  ) OVER END_DATE_YEAR_ASC
                               AS DATA_NASCITA,
  FIRST_VALUE(
    CONCAT_WS('/',A.END_DATE_DAY::text,A.END_DATE_MONTH::text,A.END_DATE_YEAR::text)
  ) OVER END_DATE_YEAR_ASC
                               AS DATA_MORTE
FROM
  <your query, without the ORDER BY>
WINDOW
  END_DATE_YEAR_ASC AS (ORDER BY A.END_DATE_YEAR)

Однако ваше предложение WHERE является "подозрительным" ...

Сначала ...

  • > ALL(<some dates) == > ( MAX(<some_dates>) )
  • <= ALL(<some dates) == <= ( MIN(<some_dates>) )

Разве вы не ожидаете, что там будет NULL с?

Итак, это дает ...

WHERE
      AT.NAME LIKE 'Per%'
  AND A.END_DATE_YEAR
      >
      (
        # Latest [END_DATE_YEAR]
        #   Where that [END_DATE_YEAR] is before (or equal to)
        #     Earliest [END_DATE_YEAR] for 'Lou%'
        ############################################################
        SELECT MAX(A.END_DATE_YEAR)
          FROM artist AS A
          JOIN artist_type AS AT ON A.TYPE = AT.ID
         WHERE AT.NAME LIKE 'Per%'
           AND A.END_DATE_YEAR
               <=
               (
                 # Earliest [END_DATE_YEAR] for 'Lou%'
                 ############################################################
                 SELECT MIN(A.END_DATE_YEAR)
                   FROM artist AS A
                   JOIN artist_type AS AT ON A.TYPE = AT.ID
                  WHERE AT.NAME LIKE 'Per%'
                    AND A.NAME LIKE 'Lou%'
               )
      )
  • Найдите самую раннюю дату смерти всех Lou% художников.
  • Найдите самую последнюю дату смерти, которая произошла до этого.
  • Найдите самую раннюю смерть, которая произошлапосле этого.

Разве это не смерть первого 'Lou%' умершего ???

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...