Сложный запрос на объединение.

Antexnew
Дата: 30.01.2013 11:12:01
Здраствуйте.
Подскажите пожалуйста как можно составить следующий запрос:
Есть таблица topics: id, time_last
1 17
2 25
3 14
4 37
5 39
6 8
7 10
8 30
9 27
И еще одна topics_view: id, time_v
1 20
4 12
9 30

Мне нужно получить результат, в котором будут выбраны записи из таблицы topics, где time_last>15, а так же для каждой соотвествующей строки topics.time_last>topics_view.time_v.
Причем, если в таблице topics_view некоторые записи отсутствуют, то они должны присутствовать в результате.
То есть результирующая табличка должна быть такой:
2 25
4 37
5 39
8 30
Добрый Э - Эх
Дата: 30.01.2013 11:52:42
left join по неэквиусловию. в чем сложность?
hallabud
Дата: 30.01.2013 12:33:02
SELECT t.id, t.time_last
FROM
  topics t
LEFT JOIN topics_view tw
ON t.id = tw.id
WHERE
  t.time_last > 15
  AND t.time_last > IFNULL(tw.time_v,0);
DBConstructor
Дата: 30.01.2013 17:41:15
Antexnew, это домашняя работа по информатике?
Если знающий человек представит решение, то окажет вам медвежью услугу. Я бы не стал...
hallabud
Дата: 30.01.2013 17:58:23
DBConstructor
Antexnew, это домашняя работа по информатике?
Если знающий человек представит решение, то окажет вам медвежью услугу. Я бы не стал...

Нет, ТС судя по всему какой-то форум ваяет.
Antexnew
Дата: 30.01.2013 23:29:23
Этот запрос помог:
select t.id, t.time_last from topics t left join topics_view tv using(id) where time_last>15 and (time_last>time_v or time_v is null)


Но в процессе пришлось ввести некоторые корректировки в исходные данные:

Таблица topics: id, razd_id, time_last
1 4 24
2 2 36
3 3 19
4 3 45
5 8 11
6 9 12
7 4 75
8 1 37
9 2 24
10 5 21
11 6 4
12 3 12
13 8 31
14 3 42
15 3 31
16 3 47

Таблица topics_view: id, user_id, time_v
4 2 27
8 4 42
2 8 18
9 1 34
13 3 13
7 2 39
10 7 11
13 7 28
10 2 31
9 11 17
14 2 54
8 1 12
16 2 20
11 6 19

Нужно получить результат, в котором будут выбраны записи из таблицы topics(id, time_last) присоединить поле time_v из
таблицы topics_view, ГДЕ time_last>15 и razd_id=3, а так же для каждой соотвествующей строки
topics.time_last>topics_view.time_v, - ИЗ таблицы topics_view сравнение производить только для записей, где user_id=2.
Причем, если в таблице topics_view некоторые записи отсутствуют, то они должны присутствовать в результате.

То есть результирующая табличка должна быть такой:
3 19 NULL
4 45 27
15 31 NULL
16 47 20

Делаю такой запрос:
SELECT t.id, t.time_last, tv.time_v FROM topics AS t
LEFT JOIN topics_view AS tv USING(id)
WHERE t.time_last>15 AND t.razd_id=3 AND tv.user_id=2
AND(t.time_last>tv.time_v OR tv.time_v IS NULL)


Но этот запрос возвращает неверный результат...
hallabud
Дата: 31.01.2013 18:04:31
Antexnew
Но этот запрос возвращает неверный результат...

Это очевидно, так как запрос выводит только записи, у которых tv.user_id = 2.

Вам нужно в блоке WHERE использовать конструкцию CASE:
SELECT t.id, t.time_last, tv.time_v
  FROM topics t
   LEFT JOIN topics_view tv
    ON t.id = tv.id
WHERE t.time_last > 15 AND t.razd_id = 3
  AND CASE WHEN tv.user_id = 2 THEN t.time_last > tv.time_v ELSE 1=1 END;
Antexnew
Дата: 01.02.2013 09:55:53
hallabud, ваш запрос возвращает немного не тот результат, который нужно. Потестировал его с разными данными.

Нужные данные возвращает этот запрос:
SELECT t.id, t.time_last, tv.time_v FROM topics AS t
LEFT JOIN (SELECT * FROM topics_view WHERE topics_view.user_id=2) AS tv USING(id)
WHERE t.time_last>15 AND t.razd_id=3
AND(t.time_last>tv.time_v OR tv.time_v IS NULL)
Antexnew
Дата: 01.02.2013 10:02:10
Так же нужные данные возвращает такой запрос (0.0198 сек.).
SELECT t.id, t.time_last, tv.time_v
FROM topics AS t
LEFT JOIN topics_view tv ON t.id=tv.id AND tv.user_id=2
WHERE t.time_last>15 AND t.razd_id=3 AND t.time_last>IFNULL(tv.time_v, 0);

Но он работает ощутимо дольше - (0.0198 сек.), против (0.0007 сек.) - для запроса в предыдущем моем сообщении.
Правда тестировал на маленьких табличках по 16 записей всего.
Полагаю что на большем объеме данных запрос из предыдущего сообщения так же будет выигрывать в скорости.

Интересно, есть ли еще более оптимальные решения для моей задачи?
hallabud
Дата: 01.02.2013 12:57:26
Предложенные вами варианты не соответствуют постановке задачи.
Antexnew
LEFT JOIN topics_view tv ON t.id=tv.id AND tv.user_id=2

или
Antexnew
LEFT JOIN (SELECT * FROM topics_view WHERE topics_view.user_id=2)

присоединит из топикс_вью только те записи, у которых user_id=2
Antexnew
То есть результирующая табличка должна быть такой:
3 19 NULL
4 45 27
15 31 NULL
16 47 20

Такую результирующую табличку вы не получите.
Antexnew
hallabud, ваш запрос возвращает немного не тот результат, который нужно

Именно тот, которые вы указали как желаемый.