Написание запроса с использованием LEFT JOIN
От: dreamcharger  
Дата: 05.12.06 00:47
Оценка:
Возник вопрос по выборке записей.

Есть некая таблица, при выборке записей из которой, некоторые поля следует выбирать из 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, и ее следует сранивать/получать из второй или третей таблицы.
Re: Написание запроса с использованием LEFT JOIN
От: _d_m_  
Дата: 05.12.06 03:56
Оценка:
Здравствуйте, dreamcharger, Вы писали:

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>


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

Только сомневаюсь в эффективном плане этого запроса. Но это уже смотри на месте
Re: Написание запроса с использованием LEFT JOIN
От: Sshur Россия http://shurygin-sergey.livejournal.com
Дата: 05.12.06 06:21
Оценка:
Здравствуйте, 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, а в остальных — только их специфичные поля. Тогда не будет проблем с выбором по дате.
Шурыгин Сергей

"Не следует преумножать сущности сверх необходимости" (с) Оккам
Re: Написание запроса с использованием LEFT JOIN
От: alico  
Дата: 05.12.06 10:08
Оценка:
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
От: _d_m_  
Дата: 05.12.06 11:09
Оценка:
Здравствуйте, 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>WHERE ISNULL(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
От: alico  
Дата: 05.12.06 11:36
Оценка:
Здравствуйте, _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>>WHERE ISNULL(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
От: dreamcharger  
Дата: 05.12.06 13:27
Оценка:
Здравствуйте, alico, Вы писали:

A>Во-вторых можно отрезать заведомо неподходящие записи в условиях джойнов

A>В-третьих я бы копал структуру, а не запрос

Да, наверно вы правы, мне следует пересмотреть структуру таблиц.

Я релизовал данный вопрос с помощью view, кстати, тут же вопрос, насколько уместно городить большие по длине запросы при обращении к серверу, или логичнее создать требуемый view, и выбирать простым запросом уже из него.
Re[5]: Написание запроса с использованием LEFT JOIN
От: alico  
Дата: 05.12.06 13:37
Оценка:
Здравствуйте, dreamcharger, Вы писали:

D>Здравствуйте, alico, Вы писали:


A>>Во-вторых можно отрезать заведомо неподходящие записи в условиях джойнов

A>>В-третьих я бы копал структуру, а не запрос

D>Да, наверно вы правы, мне следует пересмотреть структуру таблиц.


D>Я релизовал данный вопрос с помощью view, кстати, тут же вопрос, насколько уместно городить большие по длине запросы при обращении к серверу, или логичнее создать требуемый view, и выбирать простым запросом уже из него.


Плюс вьюхи:
1) запрос уже скомпилирован, т.е. выполняется чуть-чуть быстрее
2) удобнее пользоваться
3) в некоторых субд можно индекс на вьюху создать, не уверен, можно ли это в мсскл? Если да, то решается вопрос оптимизации данной задачи

А вообще зависит от ситуации. Если данное обращение частое, либо из разных мест, либо и то и то, то уместно создать вьюху. Если же у Вас одно место в системе, откуда такой запрос нужен, и больше ниоткуда с большой вероятностью не понадобится, то создавать лишний объект базы данных нет необходимости.

Кстати, а что Вы называете большим запросом? Если тот, что мы здесь рассматривали, то Вы не видели больших запросов
Re[6]: Написание запроса с использованием LEFT JOIN
От: Alex S Украина  
Дата: 05.12.06 15:47
Оценка:
...

A>Плюс вьюхи:

A>1) запрос уже скомпилирован, т.е. выполняется чуть-чуть быстрее
A>2) удобнее пользоваться
A>3) в некоторых субд можно индекс на вьюху создать, не уверен, можно ли это в мсскл? Если да, то решается вопрос оптимизации данной задачи

Да, таки можно (MS SQL их поддерживает). Нужно только думать на счет того, что нужно оптимизировать: создание индексированного представления (indexed view) негативно влияет на скорость добавления/обновления данных в используемых таблицах (причем нелинейно, т.е. 3 indexed view затормаживают более чем в 3 раза). Если данные изменяются чаще, чем запрашиваются, то это может себя не оправдать.

A>А вообще зависит от ситуации. Если данное обращение частое, либо из разных мест, либо и то и то, то уместно создать вьюху. Если же у Вас одно место в системе, откуда такой запрос нужен, и больше ниоткуда с большой вероятностью не понадобится, то создавать лишний объект базы данных нет необходимости.


A>Кстати, а что Вы называете большим запросом? Если тот, что мы здесь рассматривали, то Вы не видели больших запросов
Re[7]: Написание запроса с использованием LEFT JOIN
От: alico  
Дата: 05.12.06 16:47
Оценка:
Здравствуйте, Alex S, Вы писали:

AS>...


A>>Плюс вьюхи:

A>>1) запрос уже скомпилирован, т.е. выполняется чуть-чуть быстрее
A>>2) удобнее пользоваться
A>>3) в некоторых субд можно индекс на вьюху создать, не уверен, можно ли это в мсскл? Если да, то решается вопрос оптимизации данной задачи

AS>Да, таки можно (MS SQL их поддерживает). Нужно только думать на счет того, что нужно оптимизировать: создание индексированного представления (indexed view) негативно влияет на скорость добавления/обновления данных в используемых таблицах (причем нелинейно, т.е. 3 indexed view затормаживают более чем в 3 раза). Если данные изменяются чаще, чем запрашиваются, то это может себя не оправдать.


Безусловно
Re[4]: Написание запроса с использованием LEFT JOIN
От: _d_m_  
Дата: 06.12.06 04:44
Оценка:
Здравствуйте, 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>>>WHERE ISNULL(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
От: _d_m_  
Дата: 06.12.06 04:49
Оценка:
Здравствуйте, alico, Вы писали:

A>Плюс вьюхи:

A>1) запрос уже скомпилирован, т.е. выполняется чуть-чуть быстрее

Но-но! Хде ваши докасательства? (С) к/ф "Красная жара"
Ничего он не скомпилирован, а каждый раз оптимизатор разворачиват представление согласно своим планам оптимизации запроса. И для разных запросов планы разные.

A>2) удобнее пользоваться

A>3) в некоторых субд можно индекс на вьюху создать, не уверен, можно ли это в мсскл? Если да, то решается вопрос оптимизации данной задачи

Можно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.