Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Условие для LIMIT / 6 сообщений из 6, страница 1 из 1
07.02.2014, 08:24:06
    #38552770
VladimirMerk
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Условие для LIMIT
Здравствуйте.

Есть таблица, с двумя основными полями - uid и status
+------+--------+---------+
| id | uid | status |
+------+--------+---------+
| 1 | 1 | 1 |
| 2 | 1 | 1 |
| 3 | 1 | 0 |
| 4 | 3 | 0 |
| 5 | 3 | 0 |
| 6 | 4 | 0 |
| 7 | 4 | 1 |
| 8 | 4 | 0 |
| 9 | 4 | 1 |
| 10 | 4 | 0 |
| 11 | 5 | 0 |
| 12 | 5 | 1 |
+------+---------+---------+

Нужно сделать выборку id по определенным условиям (uid > n и status = 1)
НО нужно, чтобы возвращались все подходящие строки только для одного uid, который я заранее не знаю. Пример:
Код: plsql
1.
SELECT id FROM table WHERE uid > 0 AND status = 1


Мне нужны строки 1 и 2 только для uid 1, т.к. на него пришлось первое вхождение
Другой пример:
Код: plsql
1.
SELECT id FROM table WHERE uid > 1 AND status = 1


В данном случае нужны строки 7 и 9, т.к. первое вхождение по условию пришлось на uid 4 и у него 2 совпавших поля.

Пробую сделать при помощи переменной:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SET @uid:= NULL;
SELECT
    t.id,
    @uid := t.uid
FROM 
    table t
WHERE 
    t.uid > 0
    AND (@uid IS NULL OR t.uid = @uid) 
    AND t.status = 1



Возвращает то что нужно - 1 и 2
Все замечательно получилось, но когда применил данный способ в проекте, вылезла неприятная вещь - запрос возвращает чушь после применения сортировки ORDER BY t.uid ASC;
Без сортировки не обойтись никак. Если в таблице значения uid идут не по порядку (что в проекте - обычное дело):
+------+--------+---------+
| id | uid | status |
+------+--------+---------+
| 5 | 3 | 0 | <сначала 3
| 6 | 4 | 0 |
| 7 | 4 | 1 |
| 8 | 4 | 0 |
| 9 | 4 | 1 |
| 10 | 4 | 0 |
| 11 | 5 | 1 |
| 12 | 5 | 1 |
| 13 | 6 | 0 |
| 14 | 1 | 1 | <затем 1
| 15 | 1 | 1 |
| 16 | 4 | 1 |
+------+---------+---------+

То при том же запросе с t.uid > 0 вернет строки для uid = 4, т.к. она стоит раньше, а записи для uid = 1 не вернет НИКОГДА.

После модификации запроса и добавления к нему ORDER BY t.uid ASC по логике должно вернуть 14 и 15 строки, но результат оказывается непредсказуем:
Возвращает по порядку 14, 15, 7, 9, 16, 11, 12 - хотя на первых двух результатах ему следовало остановиться.

Самый очевидный вариант:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT t1.id, t1.uid FROM t1 
   WHERE  t1.status = 1 AND  t1.uid = (SELECT uid 
      FROM t1 
      WHERE t1.uid>0
      AND t1.status = 1 
      LIMIT 1
      ORDER BY t.uid ASC
   )


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

В чем может быть проблема моего варианта?
Или может я некорректный способ выбрал для реализации данной задачи?
...
Рейтинг: 0 / 0
07.02.2014, 08:31:04
    #38552775
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Условие для LIMIT
VladimirMerk
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT t1.id, t1.uid FROM t1 
   WHERE  t1.status = 1 AND  t1.uid = (SELECT uid 
      FROM t1 
      WHERE t1.uid>0
      AND t1.status = 1 
      LIMIT 1
      ORDER BY t.uid ASC
   )

explain посмотрите
есть там строчка с dependent subquery ?
или тут покажите
сдаётся мне, что вам поможет
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
SELECT t1.id, t1.uid 
FROM t1 
join (
 SELECT uid 
 FROM t1 
 WHERE t1.uid>0
  AND t1.status = 1 
 LIMIT 1
 ORDER BY t.uid ASC
) t0 using (uid)
WHERE  t1.status = 1


P.S. Надеюсь, индекс по uid имеется?
...
Рейтинг: 0 / 0
07.02.2014, 10:22:46
    #38552876
VladimirMerk
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Условие для LIMIT
tanglir, да, такой индекс есть. Dependent subquery была в эксплейне. Попробовал Ваш способ. Стало быстрее, но все равно - с этим джойном медленне в 32 раза. В проекте запрос выглядит так:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
SELECT
	field(1), field(2), field(3), field(n)...
FROM 
	table t

	
JOIN 
	(SELECT 
		uid 
	FROM 
		table
	LEFT JOIN table2 ON 
		...
	LEFT JOIN table3 ON
		...
	LEFT JOIN table4 ON 
		...
	LEFT JOIN table5 ON 
		...
	WHERE 
		uid > 0 
		AND ...
		AND ...
		AND ...
		AND ...
		AND ...
		AND	...
		AND	...
		ORDER BY uid ASC LIMIT 1
	) t using (uid)


LEFT JOIN table2 ON 
	...
LEFT JOIN table3 t3 ON
	...
LEFT JOIN table4 t4 ON 
	...
LEFT JOIN table5 t5 ON 
	...
WHERE 
	...
	AND ...
	AND ...
	AND ...
	AND	...
	AND ...
	AND	...
ORDER BY t.id ASC LIMIT 1



Как видите, в запросе 4 лефт джойна, получается что при подзапросе, или джойне в вашем случае - количество лефт-джойнов повышается в 2 раза. Запрос сам по себе не быстрый. Может есть еще какие-то варианты?
...
Рейтинг: 0 / 0
07.02.2014, 11:10:06
    #38552950
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Условие для LIMIT
VladimirMerkСамый очевидный вариант:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT t1.id, t1.uid FROM t1 
   WHERE  t1.status = 1 AND  t1.uid = (SELECT uid 
      FROM t1 
      WHERE t1.uid>0
      AND t1.status = 1 
      LIMIT 1
      ORDER BY t.uid ASC
   )


Не, самый очевидный - это
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
SELECT t1.id, t1.uid 
FROM t1 
WHERE  t1.status = 1 
  AND  t1.uid = (
    SELECT MIN(uid)
    FROM t1 
    WHERE t1.uid>0
      AND t1.status = 1 
    )
...
Рейтинг: 0 / 0
07.02.2014, 11:16:00
    #38552956
Cygapb-007
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Условие для LIMIT
VladimirMerkВсе замечательно получилось, но когда применил данный способ в проекте, вылезла неприятная вещь - запрос возвращает чушь после применения сортировки ORDER BY t.uid ASC;
Без сортировки не обойтись никак. SELECT из вложенного запроса с внешней сортировкой не пробовали?
Код: sql
1.
2.
3.
4.
5.
select *
from (
  select ..
  ) i
order by ...
...
Рейтинг: 0 / 0
08.02.2014, 14:38:04
    #38554390
deblogger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Условие для LIMIT
авторНО нужно, чтобы возвращались все подходящие строки только для одного uid, который я заранее не знаю.

Похоже на потребность в group by

group by uid having uid>@value
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Условие для LIMIT / 6 сообщений из 6, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]