2015-07-17 2 views
1

У меня есть два отдельных запроса, оба из которых работают.Объединение двух сложных запросов

SELECT MAX(instances) 
FROM (
    SELECT FK_Hour, day As day, Count(FK_Hour) As instances 
    FROM (
     Select slottime.FK_Hour, time.day 
     From slottime INNER JOIN time ON slottime.FK_Hour = time.Hour 
     ) As C 
    GROUP By FK_Hour 
    ) AS counts 
GROUP By day 

и

Select slot.SlotNo As FK_SlotNo 
FROM 
    (Programme INNER JOIN Module 
     ON Programme.COURSE = Module.FK_Course) 
    INNER JOIN (Slot 
       INNER JOIN SlotDemo ON Slot.SlotNo = SlotDemo.FK_SlotNo) 
     ON Module.ModuleCode = Slot.FK_ModuleCode 
GROUP BY Slot.SlotNo, Programme.C_val 
HAVING (((Count(SlotDemo.FK_Demonstrator))<5) AND ((Programme.C_val)<6)) 

Первый запрос является мясо материи, но я ищу, чтобы уточнить свои результаты (с использованием второго запроса).

Однако результат немного беспорядка (и, без каких-либо огромных сюрпризов, не работает):

SELECT MAX(instances) 
    FROM (SELECT FK_Hour, day As day, Count(FK_Hour) As instances 
     FROM (Select slottime.FK_Hour, slottime.FK_SlotNo, time.day 
      From slottime INNER JOIN time ON slottime.FK_Hour = time.Hour) 
       FROM (Select slot.SlotNo As FK_SlotNo 
        FROM (Programme INNER JOIN Module ON Programme.COURSE = Module.FK_Course) INNER JOIN (Slot INNER JOIN SlotDemo ON Slot.SlotNo = SlotDemo.FK_SlotNo) ON Module.ModuleCode = Slot.FK_ModuleCode 
        GROUP BY Slot.SlotNo, Programme.C_val 
        HAVING (((Count(SlotDemo.FK_Demonstrator))<5) AND ((Programme.C_val)<6))) 
      As C GROUP By FK_Hour 
     ) 
     AS counts GROUP By day 

Yikes.

Не может не чувствовать, что я собираюсь сделать это совершенно неправильно. Должен ли я пытаться объединить два запроса - или что-то совсем другое?

relationships of tables

Примечание это база данных MySQL, вид отношения доступа только для иллюстрации.

+0

Первый запрос действительно не имеет большого смысла. Вы просто получите неопределенный (обычно «последний») «день» из внутреннего «GROUP BY», который вы позже используете для внешнего «GROUP BY»; и самый внутренний запрос фактически не должен быть подзапросом того, кто его охватывает. – Uueerdo

+0

@Uueerdo Нет, он действительно работает - он возвращает число на каждый день, что действительно то, что я ищу. Я тестировал его с образцовыми данными, и, похоже, с ним не было никаких проблем. – Stumbler

+0

Какую базу данных вы используете?Если ваш db поддерживает CTE, это может быть хорошим вариантом. – keberwein

ответ

1

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

select max(sph.instances) 
from (
    select FK_Hour, count(*) as instances 
    from slottime 
    group by FK_Hour 
) sph 
    join time t 
    on sph.FK_Hour = t.Hour 
group by t.day 

Исключая один вложенный запрос и подъем объединения с внутренним запроса к внешним один работает, потому что вы присоединяетесь ко всему первичному ключу таблица Time, а таблица SlotTime имеет отношение внешнего ключа с ней. Таким образом, объединение не отфильтровывает ни строки и не добавляет никаких строк к результатам. Он служит только для сопоставления столбца day с результатами, чтобы вы могли группировать его по самому внешнему запросу. Альтернатива, которую я представил, не только понятна, но и стандартная SQL.

Ваш второй запрос отформатирован странно, но в основном звучит. Когда вы говорите, что хотите уточнить результаты первого запроса с помощью второго, я думаю, вы хотите ограничить SlotTime s, на котором первая обращается к тем, которые связаны с Slot s, определенными через вторую. Вот один из способов:

select max(sph.instances) 
from (
    select FK_Hour, count(*) as instances 
    from slottime 
     join (
     select slot.SlotNo As FK_SlotNo 
     from Programme 
      join Module 
      on Programme.COURSE = Module.FK_Course 
      join Slot 
      on Module.ModuleCode = Slot.FK_ModuleCode 
      join SlotDemo 
      on Slot.SlotNo = SlotDemo.FK_SlotNo 
     group by Slot.SlotNo, Programme.C_val 
     having (Count(SlotDemo.FK_Demonstrator) < 5) AND (Programme.C_val < 6) 
    ) s 
     on slottime.FK_SlotNo = s.FK_SlotNo 
    group by FK_Hour 
) sph 
    join time t 
    on sph.FK_Hour = t.Hour 
group by t.day 

Используется внутреннее соединение для выполнения дополнительной фильтрации. В качестве альтернативы вы можете использовать предложение WHERE с условием IN, чтобы выполнить одно и то же.

Обратите внимание, что это зависит в значительной степени от структуры отношений, которую вы представили. В частности, он предполагает, что исходный второй запрос не будет возвращать какие-либо дубликаты, что, в свою очередь, зависит от каждого Slot.SlotNo, который должен быть связан не более чем с одним Programme.C_val. Это ваша структура отношений, которая обеспечивает это, а не запрос.

+0

А ... Я надеялся, что у меня есть торт и съесть его. Неудивительно, что, будучи заказанным днем, кажется, не является действительно возможностью. Я полагаю, что это вина структуры, которую я использовал, но у меня (и до сих пор) есть мотивы в отношении того, как она будет обрабатываться языком сценариев, который он был сформирован, чтобы соответствовать. – Stumbler

+0

Если вам нужен конкретный порядок заказа, тогда вы должны добавить соответствующее предложение 'ORDER BY'. Группировка не подразумевает упорядочение. –

+0

Хорошо, но я имею в виду, что комбинированный запрос (в отличие от первого в вашем ответе), к сожалению, возвращает только последнюю строку (или последний день). – Stumbler

Смежные вопросы