Есть некая таблица, при выборке записей из которой, некоторые поля следует выбирать из 2-х других таблиц, при условии если значения поля type = 1 лезем в одну таблицу, при type = 2 — во вторую, в обоих случаях выборка из таблиц происходит по type_id в первой таблице.
Реализовал так:
SELECT a.id, a.type, a.type_id, a.some_specific_fields,
a.text AS a_text
a.date AS a_date,
g.text AS g_text,
g.date AS g_date,
n.text AS n_text,
n.date AS n_date
FROM archive p
LEFT OUTER JOIN group_archive g ON (p.type_id = g.id AND p.type = 1)
LEFT OUTER JOIN news_archive n ON (p.type_id = n.id AND p.type = 2)
ORDER BY p.id DESC
Все работает, по возвращаемому значению type читаю данные из соответствующих полей.
Но как сделать такую же выборку записей но только за определенную дату, к примеру, чтобы date > 'December 01, 2006 00:00'?
Возможно ли это сделать одним запросом и без проверок даты в возвращаемом результате?
Замечу, что дата хранится только в одной из таблиц, то есть при услувии type <> 0 в главной таблице archive date = NULL, и ее следует сранивать/получать из второй или третей таблицы.
D>SELECT a.id, a.type, a.type_id, a.some_specific_fields,
D> a.text AS a_text
D> a.date AS a_date,
D> g.text AS g_text,
D> g.date AS g_date,
D> n.text AS n_text,
D> n.date AS n_date
D>FROM archive p
D>LEFT OUTER JOIN group_archive g ON (p.type_id = g.id AND p.type = 1)
D>LEFT OUTER JOIN news_archive n ON (p.type_id = n.id AND p.type = 2)
D>ORDER BY p.id DESC
D>
D>Все работает, по возвращаемому значению type читаю данные из соответствующих полей.
D>Но как сделать такую же выборку записей но только за определенную дату, к примеру, чтобы date > 'December 01, 2006 00:00'?
declare @MyDate datetime
set @MyDate = '20061201'
SELECT a.id, a.type, a.type_id, a.some_specific_fields,
a.text AS a_text
a.date AS a_date,
g.text AS g_text,
g.date AS g_date,
n.text AS n_text,
n.date AS n_date
FROM archive p
LEFT OUTER JOIN group_archive g ON (p.type_id = g.id AND p.type = 1)
LEFT OUTER JOIN news_archive n ON (p.type_id = n.id AND p.type = 2)
where
(a.date > @MyDate and g.date is null and n.date is null) or
(g.date > @MyDate and a.date is null and n.date is null) or
(n.date > @MyDate and g.date is null and a.date is null)
ORDER BY p.id DESC
Только сомневаюсь в эффективном плане этого запроса. Но это уже смотри на месте
Здравствуйте, dreamcharger, Вы писали:
D>Возник вопрос по выборке записей.
D>Есть некая таблица, при выборке записей из которой, некоторые поля следует выбирать из 2-х других таблиц, при условии если значения поля type = 1 лезем в одну таблицу, при type = 2 — во вторую, в обоих случаях выборка из таблиц происходит по type_id в первой таблице.
D>
D>SELECT a.id, a.type, a.type_id, a.some_specific_fields,
D> a.text AS a_text
D> a.date AS a_date,
D> g.text AS g_text,
D> g.date AS g_date,
D> n.text AS n_text,
D> n.date AS n_date
D>FROM archive p
D>LEFT OUTER JOIN group_archive g ON (p.type_id = g.id AND p.type = 1)
D>LEFT OUTER JOIN news_archive n ON (p.type_id = n.id AND p.type = 2)
D>ORDER BY p.id DESC
D>
Я в таких случаях объединяю не по горизонтали, а по вертикали:
SELECT a.id, a.type, a.type_id, a.some_specific_fields,
a.text AS a_text
a.date AS a_date,
details.text AS b_text,
details.date AS b_date,
FROM archive a
left JOIN
(select id, 1 [type], text, date from group_archive
union
select id, 2, text, date from news_archive
) details
on details.id =type_id and details.type = a.type
where (a.type = 0 and a.date > '2006-01-01') or (details.date > '2006-01-01')
Есть вопрос по данной структуре — зачем дублировать поля text,date в archive и в "дочерних" таблицах? Тем более что если есть связь, то поля text, date в archive не используются. Есть смысл text,date в любом случае хранить в таблице archive, а в остальных — только их специфичные поля. Тогда не будет проблем с выбором по дате.
Шурыгин Сергей
"Не следует преумножать сущности сверх необходимости" (с) Оккам
SELECT a.id, a.type, a.type_id, a.some_specific_fields,
a.text AS a_text
a.date AS a_date,
g.text AS g_text,
g.date AS g_date,
n.text AS n_text,
n.date AS n_date
FROM archive p
LEFT OUTER JOIN group_archive g ON (p.type_id = g.id AND p.type = 1)
LEFT OUTER JOIN news_archive n ON (p.type_id = n.id AND p.type = 2)
WHERE ISNULL(ISNULL(a.date, g.date), n.date) > 'December 01, 2006 00:00'
ORDER BY p.id DESC
Re[2]: Написание запроса с использованием LEFT JOIN
A>SELECT a.id, a.type, a.type_id, a.some_specific_fields,
A> a.text AS a_text
A> a.date AS a_date,
A> g.text AS g_text,
A> g.date AS g_date,
A> n.text AS n_text,
A> n.date AS n_date
A>FROM archive p
A>LEFT OUTER JOIN group_archive g ON (p.type_id = g.id AND p.type = 1)
A>LEFT OUTER JOIN news_archive n ON (p.type_id = n.id AND p.type = 2)
A>WHEREISNULL(ISNULL(a.date, g.date), n.date) > 'December 01, 2006 00:00'
A>ORDER BY p.id DESC
A>
Ну вот здесь железно table-scan обеспечен
Re[3]: Написание запроса с использованием LEFT JOIN
Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, alico, Вы писали:
A>>
A>>SELECT a.id, a.type, a.type_id, a.some_specific_fields,
A>> a.text AS a_text
A>> a.date AS a_date,
A>> g.text AS g_text,
A>> g.date AS g_date,
A>> n.text AS n_text,
A>> n.date AS n_date
A>>FROM archive p
A>>LEFT OUTER JOIN group_archive g ON (p.type_id = g.id AND p.type = 1)
A>>LEFT OUTER JOIN news_archive n ON (p.type_id = n.id AND p.type = 2)
A>>WHEREISNULL(ISNULL(a.date, g.date), n.date) > 'December 01, 2006 00:00'
A>>ORDER BY p.id DESC
A>>
___>Ну вот здесь железно table-scan обеспечен
Во-первых задачи оптимизации не стояло. Может у него 200 записей на все таблицы — тогда овчинка оптимизации выделки не стоит.
Во-вторых можно отрезать заведомо неподходящие записи в условиях джойнов
В-третьих я бы копал структуру, а не запрос
ЗЫ. По моему имхо, Ваш вариант запроса тоже не избежит полного сканирования результата джойна
Re[4]: Написание запроса с использованием LEFT JOIN
Здравствуйте, alico, Вы писали:
A>Во-вторых можно отрезать заведомо неподходящие записи в условиях джойнов A>В-третьих я бы копал структуру, а не запрос
Да, наверно вы правы, мне следует пересмотреть структуру таблиц.
Я релизовал данный вопрос с помощью view, кстати, тут же вопрос, насколько уместно городить большие по длине запросы при обращении к серверу, или логичнее создать требуемый view, и выбирать простым запросом уже из него.
Re[5]: Написание запроса с использованием LEFT JOIN
Здравствуйте, dreamcharger, Вы писали:
D>Здравствуйте, alico, Вы писали:
A>>Во-вторых можно отрезать заведомо неподходящие записи в условиях джойнов A>>В-третьих я бы копал структуру, а не запрос
D>Да, наверно вы правы, мне следует пересмотреть структуру таблиц.
D>Я релизовал данный вопрос с помощью view, кстати, тут же вопрос, насколько уместно городить большие по длине запросы при обращении к серверу, или логичнее создать требуемый view, и выбирать простым запросом уже из него.
Плюс вьюхи:
1) запрос уже скомпилирован, т.е. выполняется чуть-чуть быстрее
2) удобнее пользоваться
3) в некоторых субд можно индекс на вьюху создать, не уверен, можно ли это в мсскл? Если да, то решается вопрос оптимизации данной задачи
А вообще зависит от ситуации. Если данное обращение частое, либо из разных мест, либо и то и то, то уместно создать вьюху. Если же у Вас одно место в системе, откуда такой запрос нужен, и больше ниоткуда с большой вероятностью не понадобится, то создавать лишний объект базы данных нет необходимости.
Кстати, а что Вы называете большим запросом? Если тот, что мы здесь рассматривали, то Вы не видели больших запросов
Re[6]: Написание запроса с использованием LEFT JOIN
...
A>Плюс вьюхи: A>1) запрос уже скомпилирован, т.е. выполняется чуть-чуть быстрее A>2) удобнее пользоваться A>3) в некоторых субд можно индекс на вьюху создать, не уверен, можно ли это в мсскл? Если да, то решается вопрос оптимизации данной задачи
Да, таки можно (MS SQL их поддерживает). Нужно только думать на счет того, что нужно оптимизировать: создание индексированного представления (indexed view) негативно влияет на скорость добавления/обновления данных в используемых таблицах (причем нелинейно, т.е. 3 indexed view затормаживают более чем в 3 раза). Если данные изменяются чаще, чем запрашиваются, то это может себя не оправдать.
A>А вообще зависит от ситуации. Если данное обращение частое, либо из разных мест, либо и то и то, то уместно создать вьюху. Если же у Вас одно место в системе, откуда такой запрос нужен, и больше ниоткуда с большой вероятностью не понадобится, то создавать лишний объект базы данных нет необходимости.
A>Кстати, а что Вы называете большим запросом? Если тот, что мы здесь рассматривали, то Вы не видели больших запросов
Re[7]: Написание запроса с использованием LEFT JOIN
Здравствуйте, Alex S, Вы писали:
AS>...
A>>Плюс вьюхи: A>>1) запрос уже скомпилирован, т.е. выполняется чуть-чуть быстрее A>>2) удобнее пользоваться A>>3) в некоторых субд можно индекс на вьюху создать, не уверен, можно ли это в мсскл? Если да, то решается вопрос оптимизации данной задачи
AS>Да, таки можно (MS SQL их поддерживает). Нужно только думать на счет того, что нужно оптимизировать: создание индексированного представления (indexed view) негативно влияет на скорость добавления/обновления данных в используемых таблицах (причем нелинейно, т.е. 3 indexed view затормаживают более чем в 3 раза). Если данные изменяются чаще, чем запрашиваются, то это может себя не оправдать.
Безусловно
Re[4]: Написание запроса с использованием LEFT JOIN
Здравствуйте, alico, Вы писали:
___>>Здравствуйте, alico, Вы писали:
A>>>
A>>>SELECT a.id, a.type, a.type_id, a.some_specific_fields,
A>>> a.text AS a_text
A>>> a.date AS a_date,
A>>> g.text AS g_text,
A>>> g.date AS g_date,
A>>> n.text AS n_text,
A>>> n.date AS n_date
A>>>FROM archive p
A>>>LEFT OUTER JOIN group_archive g ON (p.type_id = g.id AND p.type = 1)
A>>>LEFT OUTER JOIN news_archive n ON (p.type_id = n.id AND p.type = 2)
A>>>WHEREISNULL(ISNULL(a.date, g.date), n.date) > 'December 01, 2006 00:00'
A>>>ORDER BY p.id DESC
A>>>
___>>Ну вот здесь железно table-scan обеспечен
A>Во-первых задачи оптимизации не стояло. Может у него 200 записей на все таблицы — тогда овчинка оптимизации выделки не стоит. A>Во-вторых можно отрезать заведомо неподходящие записи в условиях джойнов A>В-третьих я бы копал структуру, а не запрос
Полностью согласен и также думаю.
A>ЗЫ. По моему имхо, Ваш вариант запроса тоже не избежит полного сканирования результата джойна
Ну я тоже сомневаюсь в эффективности плана, о чем и написал. Но вариант с isnull не оставляет даже сомнений.
Re[6]: Написание запроса с использованием LEFT JOIN
Здравствуйте, alico, Вы писали:
A>Плюс вьюхи: A>1) запрос уже скомпилирован, т.е. выполняется чуть-чуть быстрее
Но-но! Хде ваши докасательства? (С) к/ф "Красная жара"
Ничего он не скомпилирован, а каждый раз оптимизатор разворачиват представление согласно своим планам оптимизации запроса. И для разных запросов планы разные.
A>2) удобнее пользоваться A>3) в некоторых субд можно индекс на вьюху создать, не уверен, можно ли это в мсскл? Если да, то решается вопрос оптимизации данной задачи