Как перебрать объединенные данные в два или более вложенных цикла? - PullRequest
1 голос
/ 23 апреля 2009

Некоторое время назад я задал вопрос о вложенных циклах в SO, и как это было, внутри циклов моего примера были запросы, и я получил четкий ответ:

НИКОГДА НИКОГДА не помещайте SQL-запрос в цикл

Я пробовал с тех пор, и в основном это работает. Просто нужно приложить усилие и написать запрос, который извлекает все, что вам нужно сразу.

НО что вы делаете, когда у вас есть набор данных из запроса JOIN, который содержит вложенные данные, которые вам нужно вывести вложенным способом?

Пример объединения из таблиц A и B:

A.a     |  B.a     |  B.b
--------|----------|-------------
fruits  |  banana  |  yellow
fruits  |  apple   |  red
animals |  zebra   |  black&white
animals |  elefant |  gray
animals |  fox     |  red
planets |  earth   |  blue
planets |  mars    |  red

хорошо, теперь я получил все это в массиве или наборе строк, и теперь мне нужно отобразить что-то вроде этого:

фрукты

  • желтый банан
  • красное яблоко

животные

  • черно-белая зебра
  • серый слон
  • рыжая лиса

планеты

  • голубая земля
  • красный марс

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

Сейчас я делаю это по-старому:

query groups

foreach groups
{
    query animals in group
    foreach animal
}

но эй, НИКОГДА НИКОГДА не ставь sql внутри цикла. так что мне делать? Я делаю PHP, но я думаю, что это вопрос мета.

Ответы [ 2 ]

3 голосов
/ 23 апреля 2009

Использовать алгоритм прерывания управления.

Я бы вернул набор результатов точно так, как вы видите в вопросе:

A.a     |  B.a     |  B.b
--------|----------|-------------
fruits  |  banana  |  yellow
fruits  |  apple   |  red
animals |  zebra   |  black&white
animals |  elefant |  gray
animals |  fox     |  red
planets |  earth   |  blue
planets |  mars    |  red

цикл по всем строкам:

  • при изменении A.a вывести заголовок
  • затем всегда выводите значение B.b + B.a

псевдокод для приложения, вызывающего SQL:

set last_A = null
exec query

loop over result set {
    if last_A == null or fetch_A!=last_A {
        last_A=fetch_A
        display fetch_a
    }
    display fetch_Bb + fetch_Ba
    }
}//loop
1 голос
/ 23 апреля 2009

Если то, что у вас есть, это иерархия, «ориентированный ациклический граф». SQL не делает этого.

Есть и другие вещи теории графов, которые SQL не делает.

Поскольку SQL этого не делает, правило «никогда не помещать SQL в цикл» выходит из окна.

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

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

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

Это будет один выбор со сложными циклами вокруг набора результатов. Один выбор - не в цикле - и сложный цикл для обработки одного набора результатов.

...