ORDER BY RAND и внутригрупповая сортировка?

REMO

Guest
ORDER BY RAND и внутригрупповая сортировка?

Таблица:

id | property_id
1001 | 101
1001 | 102
1002 | 103
1002 | 101

id повторяется. Как сделать выборку так, чтобы id шли рандомом. Но при этом, внутри группы каждого айди сохранялся порядок property_id.

Т.е. результат должен быть (к примеру):

1002 | 101
1002 | 103
1001 | 101
1001 | 102

Т.е. id рандомом, а внутри каждого айди property_id по порядку (101, 102, ..., 10n)?
 

Kucovsky

Новичок
Очень часто бывают ситуации когда проще и быстрее сделать два запроса а не один,хоть и очень мудренный.

Я думаю,тут похожий случай.

Первый запрос

SELECT distinct id as foundId from table ORDER by RAND()

И уже внутри цикла другой запрос

SELECT property_id from table where id = foundId order by property_id
 

REMO

Guest
Автор оригинала: Kucovsky
Очень часто бывают ситуации когда проще и быстрее сделать два запроса а не один,хоть и очень мудренный.

Я думаю,тут похожий случай.

Первый запрос

SELECT distinct id as foundId from table ORDER by RAND()

И уже внутри цикла другой запрос

SELECT property_id from table where id = foundId order by property_id
Тогда получится не 2 запроса. А 1+количество оборотов цикла. Это как раз то, от чего я сейчас пытаюсь уйти :(

А как сделать 2-мя запросами вообще, я что то не представляю.
 

Kucovsky

Новичок
Можно очень "извратиться и написать" запрос.
Но обычно от программы требуется "чтоб работало и быстро",при этом красоту кода может оценить только "эстет".

Поэтому можно и одним запросом.

Попробуй select *from table.

А потом отсортируй полученный массив с помощью РНР.

Можеет и заработает быстрее,все зависит от размеров таблицы.
 

REMO

Guest
Автор оригинала: Kucovsky
Можно очень "извратиться и написать" запрос.
Но обычно от программы требуется "чтоб работало и быстро",при этом красоту кода может оценить только "эстет".

Поэтому можно и одним запросом.

Попробуй select *from table.

А потом отсортируй полученный массив с помощью РНР.

Можеет и заработает быстрее,все зависит от размеров таблицы.
ПХП не совсем подходит. Дело в том, что присутствует постраничный вывод. При изменении количества выводимых на странице товаров порядок (рандомный) должен сохранится. Это достигается при помощи ORDER BY RAND(number).

Поэтому придется извращаться, но как?

-~{}~ 12.06.04 13:43:

Я еще раз поясню задачу. К примеру есть 10 товаров, у каждого товара есть от 3 до 5 своиств.

Необходимо, чтобы товары выводились в случайном порядке, а своиства для каждого товара (это подгруппа как бы) были отсортированы по возрастанию их айди. Может так станет понятнее чего я хочу получить.
 

lucas

Guest
Необходимо, чтобы товары выводились в случайном порядке
Зачем?

Чтобы зашел пользователь, выбрал себе соковыжималку, запомнил, что она находится на стр. 4, а на следующий день, созрев для покупки, там ее не обнаружил?
 

REMO

Guest
Автор оригинала: lucas
Зачем?

Чтобы зашел пользователь, выбрал себе соковыжималку, запомнил, что она находится на стр. 4, а на следующий день, созрев для покупки, там ее не обнаружил?
Зачем это уже другой вопрос, так хочет заказчик :) Мое дело реализовать то, что просят...
 

Kucovsky

Новичок
Я вижу есть две возможности
1)Поиграться с массивами РНР
2)Использовать временную таблицу

Попробуй чего-такое

CREATE TEMPORARY TABLE tmp_tbl SELECT DISTINCT id FROM table order by rand();
SELECT * from tmp_tbl LEFT JOIN table USING (id)



Это только схема но по моему это очень сильное "извращение"
 

REMO

Guest
Автор оригинала: Kucovsky
Я вижу есть две возможности
1)Поиграться с массивами РНР
2)Использовать временную таблицу

Попробуй чего-такое

CREATE TEMPORARY TABLE tmp_tbl SELECT DISTINCT id FROM table order by rand();
SELECT * from tmp_tbl LEFT JOIN table USING (id)

Это только схема но по моему это очень сильное "извращение"
Согласен, но что делать задачу решать как то надо. Я лично не знаю как можно сделать ORDER BY RAND(number) в ПХП. Иначе давно бы уже сделал.

Т.е. идея в том, чтобы сначала выбрать случайный порядок ай ди, а потом уже присоединять к этому порядку другие таблицы. А в JOIN LEFT нельзя использовать ORDER BY?
 

Kucovsky

Новичок
Originally posted by REMO
Согласен, но что делать задачу решать как то надо. Я лично не знаю как можно сделать ORDER BY RAND(number) в ПХП. Иначе давно бы уже сделал.


Вот из хелпа РНР
Description
void shuffle ( array array)


This function shuffles (randomizes the order of the elements in) an array. You must use srand() to seed this function. Example 1. shuffle() example


<?php
$numbers = range(1, 20);
srand((float)microtime() * 1000000);
shuffle($numbers);
while (list(, $number) = each($numbers)) {
echo "$number ";
}
?>






Т.е. идея в том, чтобы сначала выбрать случайный порядок ай ди, а потом уже присоединять к этому порядку другие таблицы. А в JOIN LEFT нельзя использовать ORDER BY?
Можно ,конечео ,но отсортирут все подряд - нельзя сделать ORDER BY RAND только по одной таблице

А по-моему твоя задача решается простейшим двойным циклом - и не надо самому себе создавать сложности
 

lucas

Guest
Kucovsky
А по-моему твоя задача решается простейшим двойным циклом - и не надо самому себе создавать сложности
Может быть, для тебя это большая новость, но на свете встречаются таблицы, содержащие значительно больше, чем 100 записей.
 

Kucovsky

Новичок
Originally posted by lucas
Kucovsky

Может быть, для тебя это большая новость, но на свете встречаются таблицы, содержащие значительно больше, чем 100 записей.
Новость:) :) :)

Так мне приходится работать например с такими таблицами


------------------------------------------
flightsAvailability 427,870 MyISAM 48.3 MB
flightsClassAvailability 3,290,989 MyISAM 281.4 MB
flightsConnection 1,860,703 MyISAM 50.0 MB

Но в данном случае Речь идет о постраничной выборке по 20-максимум 50 записей И тут действительно нечеего мудрить.
 

lucas

Guest
REMO

Сейчас ты услышишь самое здравое предложение с самого начала топика: ИЗМЕНИ СТРУКТУРУ ТАБЛИЦ НА НОРАМАЛЬНУЮ!

То, что ты имеешь сейчас, больше напоминает таблицу-связку "товары-свойства", из которой самой по себе выбирать данные бессмысленно.
 

REMO

Guest
Автор оригинала: lucas
Так работает (не проверял)?

Код:
SELECT *
FROM table_name
GROUP BY id
ORDER BY RAND(), property_id
Работать то работает. НО!! В результате запроса получается, что все id товаров расположены в случайном порядке. Т.е. 1005 1006 1002 1005.

Поэтому собрать при помощи ПХП свойства не представляется возможным, т.к. ай ди идут не по порядку... Т.е. работает, но не так как нужно.

Kucovsky
shuffle() действительн орандомит массив. Но как я уже сказал, мне нужно, чтобы при изменении количества товаров на странице случайный порядок сохранялся - ORDER BY RAND(number). А shuffle этого не дает.

-~{}~ 12.06.04 15:03:

Автор оригинала: lucas
REMO

Сейчас ты услышишь самое здравое предложение с самого начала топика: ИЗМЕНИ СТРУКТУРУ ТАБЛИЦ НА НОРАМАЛЬНУЮ!

То, что ты имеешь сейчас, больше напоминает таблицу-связку "товары-свойства", из которой самой по себе выбирать данные бессмысленно.
Таблица-связка многие ко многим имеется. А как изменить?

-~{}~ 12.06.04 15:04:

Т.е. я не улавливаю идеи, что надо изменить, чтобы можно было сделать, то что требуется.
 

lucas

Guest
Таблица "товары": id, name, description
Таблица "свойства": id, name
Таблица-связка: id товара, id свойства, еще что-то.

-~{}~ 12.06.04 17:36:

В первых двух таблицах id -- primary key.
В последней primary key -- id товара + id свойства.

Все это можно будет прекрасно проjoinить.
 

Kucovsky

Новичок
По моему у REMO точно такая-же структура и мы здесь разбираемся с третьей таблицей-связкой
 

REMO

Guest
Автор оригинала: lucas
Таблица "товары": id, name, description
Таблица "свойства": id, name
Таблица-связка: id товара, id свойства, еще что-то.

-~{}~ 12.06.04 17:36:

В первых двух таблицах id -- primary key.
В последней primary key -- id товара + id свойства.

Все это можно будет прекрасно проjoinить.
2lucas Kucovsky прав, у меня именно такая структура таблиц. И я инджою. А толку от этого?

А что значит: В последней primary key -- id товара + id свойства.. У меня id товара и id свойства это посто индексы. Как сделать primary key -- id товара + id свойства?

-~{}~ 12.06.04 19:54:

2Kucovsky Да проблема именно в 3 таблице, из-за нее возникают дополнительные ряды. И приходится извращаться с рандомной сортировкой по ай ди товаров и сортировкой по ай ди свойств товаров (для каждого товара).

Насчет одного запроса и потом еще в цикле запроса для каждого товара. Так именно сейчас и сделано. Но это же нагрузка на БД. А нагрузка важна (т.к. базу будут дергать оч часто). Поэтому я пытаюсь уйти от этого сейчас.

Только что попробовал с TEMPORARY TABLE. Вроде работает и вроде все ок. НО :) Свойства все равно ДЖОИНЯТСЯ не отсортированными. А если во втором запросе поставить ORDER BY, то отсортируется вся таблица. Т.е. я так понимаю придется делать 2 времнеммные таблицы. Второй временной будет таблица-связка отсортированная по id, id_svoistva? Или я что то упустил.

-~{}~ 12.06.04 20:21:

Сделал с 2-мя времнными таблицами, все заработало. НО сильная потеря в скрости запрос занимает: 0.32 сек...

И второе меня беспокоит то, что при какой либо серьезной нагрузке на БД создание, создание-удаление времнных таблиц еще больше увеличт время запроса. И не будет ли конфликтов в плане одной и той же таблицы (времнной) в БД? Я читал ман, но там как то непонятно про это написано :(
 

REMO

Guest
Автор оригинала: lucas
...PRIMARY KEY (id1, id2)
А то что id не уникальны, это ничего?

-~{}~ 12.06.04 22:08:

Решил проблему следующим образом.

Первый запрос:
PHP:
SELECT *
FROM tovari
LEFT JOIN place USING (place_id)
WHERE prizn1 = 1 AND prizn2 = 1
ORDER BY RAND(".$number.")
Второй запрос:
PHP:
SELECT id, svoistva.id, svoistva.svoistva
FROM tovari
LEFT JOIN tovari_svoistva ON (tovari.id = svoistva.id)
LEFT JOIN svoistva USING (id)
WHERE prizn1 = 1 AND prizn2 = 1
ORDER BY tovari.id, tovari_svoistva.id
Второй запрос обрабытывается таким образом, что создается ассоциативный массив. Ключами которго являются ай ди товаров, а элементами массива строка и свойств товара. А при выводе просто обращаемся по ай ди к масиву СВОЙСТВА.

Причем по моим тестам рабоатет быстрее, чем запрос в цикле. И как я понимаю нагрузка на БД ЗНАЧИТЕЛЬНО ниже, т.к. выполняется всего 2 запроса вместо 70-150 (кот были бы в цикле).

Я правильно все себе представляю насчет запросов?
 
Сверху