MySQL SELECT запросов без LIMIT - PullRequest
0 голосов
/ 18 декабря 2018

Я делаю курс по реляционным базам данных, MySQL, чтобы быть более конкретным.Нам нужно создать несколько запросов SELECT для проекта.Проект связан с музыкой.В нем есть таблицы для представления музыкантов (музыкант), групп (группа) и способности музыканта выполнять определенную задачу, например, петь или играть на гитаре (акт).

Таблица musician содержит:

id
name
stagename
startyear

Таблица band содержит:

code
name
type ("band" or "solo")
startyear

И, наконец, таблица act содержит:

band     (foreign key to code of "band" table)
musician (foreign key to id of "musician" table)
hability (guitarist, singer, like that... and a foreign key to another table)
earnings

У меня есть сомнения в двух упражнениях, первое просит выбрать музыкантов id и stagename, которые участвуют с большим количеством актов в группах типа solo.

Мое решение для первогоОдин из них:

SELECT ma.id, ma.stagename
FROM musician ma, act d, band ba
WHERE ma.id = d.musician
AND ba.code = d.band
AND ba.type = "solo"
GROUP BY ma.id, ma.stagename
HAVING COUNT(ma.id) = (SELECT COUNT(d2.musician) AS count
                        FROM act d2, band ba2
                        WHERE d2.band = ba2.code
                        AND ba2.type = "solo"
                        GROUP BY d2.musician
                        ORDER BY count DESC
                        LIMIT 1);

Второй очень похож на последний.Нам нужно выбрать для каждого startyear id и stagename музыканта, который может выполнять больше действий, с соответствующим количеством действий и максимумом и минимумом его кэша.Это мое решение:

SELECT ma.startyear, ma.id, ma.stagename, COUNT(ma.id) AS NumActs, MIN(d.earnings), MAX(d.earnings) 
FROM musician ma, act d, band ba
WHERE ma.id = d.musician
AND ba.code = d.band
AND ba.type = "solo"
GROUP BY ma.year, ma.id, ma.stagename
HAVING COUNT(ma.id) = (SELECT COUNT(d2.musician) AS count
                        FROM act d2, band ba2
                        WHERE d2.band = ba2.code
                        AND ba2.type = "solo"
                        GROUP BY d2.musician
                        ORDER BY count DESC
                        LIMIT 1);

Результаты с моими фиктивными данными идеальны, но мой учитель сказал нам, что мы должны избегать использования опции LIMIT, но это единственный способ получить наибольшее число, прихотя бы с тем, что мы знаем прямо сейчас.

Я видел много подзапросов после оператора FROM для решения этой проблемы, однако для этого проекта мы не можем использовать подзапросы внутри FROM.Это действительно возможно без LIMIT?

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Возможно, но гораздо хуже, чем с подзапросом в from или limit.Так что я бы никогда не использовал его в реальной жизни:)

Короче говоря, вы можете сделать что-то вроде этого:

SELECT
      m.id
    , m.stagename
FROM
    musician m
    INNER JOIN act a ON (
            a.musician = m.id
    )
    INNER JOIN band b ON (
            b.code = a.band
        AND b.type = 'solo'
    )
GROUP BY
      m.id
    , m.stagename
HAVING
    NOT EXISTS (
        SELECT
            *
        FROM
            act a2
            INNER JOIN band b2 ON (
                    b2.code = a2.band
                AND b2.type = 'solo'
            )
        WHERE
            a2.musician != a.musician
        GROUP BY
            a2.musician
        HAVING
            COUNT(a2.musician) > COUNT(a.musician)
    )
;

Я думаю, вы можете понять идею из запросаСамо по себе это довольно просто.Тем не менее, дайте мне знать, если вам нужно объяснение.

Возможно, что ваше ограничение немного отличалось, и вы не разрешали использовать подзапрос только в своей основной части FROM.

PS I 'Я также использую синтаксис INNER JOIN ... ON, так как легче увидеть, что представляют собой условия объединения таблиц и какие условия.

PPS Это может быть ошибка в запросе, поскольку у меня нет вашей структуры данных, поэтому я не могувыполнить запрос и проверить.Я только проверил, работает ли идея с моей тестовой таблицей.

0 голосов
/ 18 декабря 2018

РЕДАКТИРОВАТЬ Я просто перечитал вопрос;мое первоначальное чтение пропустило, что встроенные представления запрещены.

Мы можем избежать конструкции ORDER BY ... DESC LIMIT 1, превратив подзапрос во встроенное представление (или «производную таблицу» вна языке MySQL) и с использованием совокупности MAX().

В качестве тривиальной демонстрации этот запрос:

 SELECT b.foo
   FROM bar b
  ORDER
     BY b.foo DESC
  LIMIT 1

можно эмулировать с помощью этого запроса:

SELECT MAX(c.foo) AS foo
  FROM ( 
         SELECT b.foo
           FROM bar b
       ) c

Пример перезаписи первогозапрос в вопросе

SELECT ma.id
     , ma.stagename
  FROM musician ma
  JOIN act d
    ON d.musician = ma.id
  JOIN band ba
    ON ba.code = d.band
 WHERE ba.type = 'solo' 
 GROUP
    BY ma.id
     , ma.stagename
HAVING COUNT(ma.id) 
     = ( SELECT MAX(c.count)
           FROM ( 
                  SELECT COUNT(d2.musician) AS count
                    FROM act d2
                    JOIN band ba2
                      ON ba2.code = d2.band
                   WHERE ba2.type = 'solo'
                   GROUP
                      BY d2.musician
                ) c
       )

ПРИМЕЧАНИЕ: это демонстрация переписывания запроса в вопросе;это не гарантирует, что этот запрос (или запрос в вопросе) гарантированно вернет результат, который удовлетворяет какой-либо конкретной спецификации.А приведенная в вопросе спецификация совсем не ясна.

...