Многие запросы SQL против 1 сложного запроса - PullRequest
0 голосов
/ 10 июня 2011

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

table1
------
Id : long, auto increment
Title : string(50)
ParentId : long

table2
------
Id : long, auto increment
FirstName : string(20)
LastName : string(30)
Zip : string(5)

table2 имеет отношение один ко многим с table1, где многие включают ноль.

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

SELECT t1.Id AS tid, t1.Title, t2.Id AS oid, t2.FirstName, t2.LastName
    FROM table t1
    INNER JOIN table2 t2 ON t1.ParentId = t2.Id
    WHERE t2.Id IN
        (SELECT Id FROM table2
         WHERE Zip IN ('zip1', 'zip2', 'etc'))
    ORDER BY t2.Id DESC

Запрос находит все элементы в table1, которые принадлежат человеку в table2, где этот человек находится в одном из перечисленных почтовых индексов.

Теперь у меня проблема: я хочу показать всем пользователям (с их элементами , если доступно ) в списке почтовые индексы, а не только те, которые имеют элементы.

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

SELECT Id AS oid, FirstName, LastName FROM table2 WHERE Zip in ('zip1', 'zip2', 'etc')
foreach(result) {
    SELECT Id AS tid, Title FROM table2 WHERE ParentId = oid
}

Или я должен придумать более сложный отдельный оператор SQL? И если так, могу ли я получить небольшую помощь? Спасибо!

Ответы [ 7 ]

2 голосов
/ 10 июня 2011

Просмотр правых объединений и групп по.Это, скорее всего, даст вам запрос, который вы ищете.

2 голосов
/ 10 июня 2011

Если я правильно понимаю, изменение вашего ВНУТРЕННЕГО СОЕДИНЕНИЯ на ПРАВИЛЬНОЕ СОЕДИНЕНИЕ должно возвращать всех пользователей независимо от того, есть у них элемент или нет, столбцы элементов просто будут нулевыми для тех, у кого этого нет.

1 голос
/ 10 июня 2011

В целом, вы должны предпочесть подход «много запросов», если (и только если)

  • в итоге вы получите более простой код
  • достаточно быстро (что вам следуетвыясните это путем тестирования)

В этом случае, я подозреваю, оба условия могут не применяться.

1 голос
/ 10 июня 2011

Я согласен (и проголосовал) @Lee D и @Bueller.Тем не менее, я, как правило, выступаю за ЛЕВЫЕ ВНЕШНИЕ СОЕДИНЕНИЯ, потому что мне легче осмыслить, что с ними происходит, особенно когда вы присоединяетесь к трем или более столам.Считайте, что это так:

Начните с того, что, как вы знаете, хотите в конечном наборе результатов:

FROM table2 t2

, а затем добавьте «необязательные» данные.

FROM table2 t2
 left outer join table1 t1
  on t1.ParentId = t2.Id

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

0 голосов
/ 10 июня 2011

То, что вы описали, называется N + 1 query.У вас есть 1 начальный запрос, который возвращает N результатов, затем 1 запрос для каждого из ваших N результатов.Если N мало, разница в производительности может быть незаметной, но при увеличении N будет наблюдаться увеличение производительности.

0 голосов
/ 10 июня 2011

Если я правильно понимаю, я думаю, что вы ищете что-то вроде этого

SELECT t1.Id AS tid, t1.Title, t2.Id AS oid, t2.FirstName, t2.LastName
    FROM table t1
    RIGHT OUTER JOIN table2 t2 ON t1.ParentId = t2.Id AND Zip IN ('zip1', 'zip2', 'etc'))
    ORDER BY t2.Id DESC

Вы можете иметь несколько условий для вашего JOIN, и RIGHT OUTER выдаст вам все строки в table2, даже если они неt совпадение в таблице 1

0 голосов
/ 10 июня 2011

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

...