SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 30.01.2013 11:08:28

new_saler
Участник
Зарегистрирован: 14.11.2012
Сообщений: 23

Сложный запрос...

Здраствуйте.
Подскажите пожалуйста как можно составить следующий запрос:
Есть таблица 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

Неактивен

 

#2 30.01.2013 11:48:38

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Сложный запрос...

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);

Неактивен

 

#3 30.01.2013 23:17:55

new_saler
Участник
Зарегистрирован: 14.11.2012
Сообщений: 23

Re: Сложный запрос...

Спасибо. Это запрос работает правильно.
Но в процессе пришлось ввести некоторые корректировки в исходные данные.

Таблица 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)


Но этот запрос возвращает неверный результат...

Отредактированно new_saler (30.01.2013 23:25:10)

Неактивен

 

#4 31.01.2013 01:08:50

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Сложный запрос...

вместо
AND tv.user_id=2
AND(t.time_last>tv.time_v OR tv.time_v IS NULL)

нужно
AND((t.time_last>tv.time_v AND AND tv.user_id=2) OR tv.time_v IS NULL)
если я правильно вас понял.

Неактивен

 

#5 31.01.2013 11:41:52

new_saler
Участник
Зарегистрирован: 14.11.2012
Сообщений: 23

Re: Сложный запрос...

vasya написал:

вместо

AND tv.user_id=2
AND(t.time_last>tv.time_v OR tv.time_v IS NULL)


нужно
AND((t.time_last>tv.time_v AND AND tv.user_id=2) OR tv.time_v IS NULL)
если я правильно вас понял.

Этот запрос работает немного не так, как мне нужно.

Попробую объяснить подробнее задачу:
Сначала мне нужно из таблицы topics выбрать все записи где time_last>15 и razd_id=3 - то есть получить такой результат:
3    3  19
4    3  45
14  3  42
15  3  31
16  3  47
Затем мне нужно из таблицы topics_view выбрать все записи где user_id=2 - то есть получить такой результат:
4    2   27
7    2   39
10  2   31
14  2   54
16  2   20
А потом уже из первой подтаблицы выбрать записи, где time_last(из первой подтаблицы)>time_v(из второй подтаблицы). ПРИЧЕМ, если во второй подтаблице нет соответствующих записей, то эти записи из первой подтаблицы должны присутствовать в результате.
То есть резутьтат:
3   19   NULL   (эту выбираем, потому что её нет во второй подтабличке)
4   45   27      (эту выбираем, потому что она есть во второй подтабличке. И 45(из первой)>27 из соотв. строки из второй)
15  31   NULL  (эту выбираем, потому что её нет во второй подтабличке)
16  47   20     (эту выбираем, потому что она есть во второй подтабличке. И 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((t.time_last>tv.time_v AND tv.user_id=2) OR tv.time_v IS NULL)

работает не так, как нужно в моем случае. (он выберет всё, что мне нужно из первой таблицы, то есть первая подтаблица будет сформирована правильно, А ВОТ ИЗ ВТОРОЙ ТАБЛИЦЫ будут выбраны лишние записи (если во второй таблице нет соответствующих записей эти записи будут выбраны для любого user_id, а мне нужно только те, где user_id=2)

Отредактированно new_saler (31.01.2013 13:33:04)

Неактивен

 

#6 31.01.2013 13:45:39

new_saler
Участник
Зарегистрирован: 14.11.2012
Сообщений: 23

Re: Сложный запрос...

Попробовал немного разобраться, получилось, что верные результаты возвращает такой запрос:

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_post>tv.time_v OR tv.time_v IS NULL)

Но теперь встает вопрос, можно ли его переписать более оптимально?

Например, почему запрос ниже возвращает не те данные, которые нужно, ведь я думаю, что MySQL сначала выбирает нужные данные из 1-й таблицы, далее должен из второй таблицы выбрать все данные, где tv.user_id=2, а дальше уже проводить сравнение  ...AND(t.time_last>tv.time_v OR tv.time_v IS NULL).
На практике же происходит не так....
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)

Отредактированно new_saler (31.01.2013 13:46:42)

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson