1 Востаннє редагувалося ConTrast77 (09.06.2015 10:37:37)

Тема: Оптимізувати код, при використанні змінних @. + обчислення в запитах

Ще один з варіантів вибірки деякої кількості випадкових рядків.

КОД:
Спочатку генерується стовпчик з унікальними рандом-значеннями (integer) = numrandom.num2
Потім виконується вибірка з таблиці відповідних рядків, якщо news2.ID цих рядків (унікальне) і дорівнює кожному значенню з генерованої таблиці стовпчика numrandom.num2.

- цей код буде доданий до теми варіантів і ефективності вибірок рандом-даних, з відповідним описом
- вважав, що використання змінних SET @lalala, може мати деякий сенс в вирішенні у вибірках
- вибірка дійсно виконує умови, набирає рівно стільки рандомних (випадкових) значень, скільки потрібно, без повторів значень; тобто рівно "5" рядків, не більше і не менше.
- вибірка не може перевіряти рядки, номери яких не існують згідно отриманого переліку раному (це не потрібно)
- вибірка не може оминати рядки, якщо вони мають в особливій колонці особливе значення (але потрібно)

SET @count=0;
SET @in1=0; SET @in2=0; SET @in3=0; SET @in4=0; SET @in5=0;
SET @inX=0;
SELECT DISTINCT `blog`.`id`, `blog`.`zag_ua`, `blog`.`minitxt_ua`
FROM
    (SELECT
            blogR.id, @inX:=ROUND( RAND()* ((SELECT MAX(`id`) FROM `news2`)-100) )+100 num2, @in1,@in2,@in3,@in4,@in5
            FROM
                    # blogR.id - вибірка для розширеного розуміння, немає в ній необхідності
                    #   , як і в вибірках @in1,@in2,@in3,@in4,@in5  (вони тільки для налагодження)
                    `news2` as blogR
            where
                IF(
                    @inX NOT in (@in1,@in2,@in3,@in4,@in5),
                    
                    @count:= if(
                        (select concat (@in5:=@in4, @in4:=@in3, @in3:=@in2, @in2:=@in1, @in1:=@inX) ),
                        (select @count:=@count+1),
                        @count),
                    @count
                )<5 AND @in5=0
    ) AS numrandom,
    `news2` as blog
WHERE blog.id IN (numrandom.num2) AND @in5<>0
#  в останньому рядку коду AND @in5<>0 - я ще повинен перевірити до чого я так ставив
# умову, що рандомний рядок відповідатиме рядку з додатковою умовою AND news2.active_news ='A' не знаю куди поставити

Питання:
1. як можна змінити примусові обчислення?
що буде швидше і оптимальніше аніж такий код:

@count:= if(
  # примусове обчислення 5-ти змінних, але за допомогою SELECT і додаткової функції, яка виконує додаткову непотрібну операцію
  (select concat (@in5:=@in4, @in4:=@in3, @in3:=@in2, @in2:=@in1, @in1:=@inX) ),
  # якщо умова IF виконується, а вона завжди виконується!, тоді збільшуємо значення @count на 1 теж за допомогою SELECT
  (select @count:=@count+1),
  # якщо IF не виконуєтся, а цього просто не може бути за даним кодом, тому просто для логіки повертаємо @count, хоча можемо поставити аби яке цифрове значення.... для швидкості
  @count)

2. чи потрібно змінювати вираз, і чи буде обчислення швидше?, (сам не перевіряв)
select concat (@in5:=@in4, @in4:=@in3, @in3:=@in2, @in2:=@in1, @in1:=@inX)
на іншу логіку, select concat (@inTXT, ', ', @inX, ' ')

і перевіряти тоді не виразом IF(@inX NOT in (@in1,@in2,@in3,@in4,@in5) ...
а виразом IF( LOCATE(' '+@inX+' ', @inTXT)=0 ... ... ,чи так можна? без (LOCATE(concat(..), ...)

3. DISTINCT таки є в коді, використовую бо в мене помилка в підготовці умов?
Не розумію, чому в вибірці SELECT `blog`.`id`, `blog`.`zag_ua`, `blog`.`minitxt_ua`
мені знадобився DISTINCT , не розумію чому генерується зайвий рядок або рядки, в умові IF(),
якщо виник збіг деякого нового отриманого значення @inX, з значенням із згенерованого набору @in1-@in4


Тепер код, який можна вважати зменшеним від першого з видаленням зайвого і зменшенням умов:

Прихований текст
SET @count=0;
SET @in1=0; SET @in2=0; SET @in3=0; SET @in4=0; SET @in5=0;
SET @inX=0;
SELECT DISTINCT `blog`.`id`, `blog`.`zag_ua`, `blog`.`minitxt_ua`
FROM
    (SELECT
            @inX:=ROUND( RAND()* ((SELECT MAX(`id`) FROM `news2`)-100) )+100 num2
            FROM
                    `news2` as blogR
            where
                IF(
                    @inX NOT in (@in1,@in2,@in3,@in4,@in5),
                    
                    @count:= if(
                        (select concat (@in4:=@in3, @in3:=@in2, @in2:=@in1, @in1:=@inX) ),
                        (select @count:=@count+1),
                        @count),
                    @count
                )<5
    ) AS numrandom,
    `news2` as blog
WHERE blog.id IN (numrandom.num2)

2

Re: Оптимізувати код, при використанні змінних @. + обчислення в запитах

Ви явно занадто закрутили і питання, і свій код.

По-суті, по двом першим питанням: ви питаєте яка з функцій - concat() чи locate() - буде працювати швидше?
По-третьому питанні: спростіть логіку, щоб розібратись що у вас працює не так.

3

Re: Оптимізувати код, при використанні змінних @. + обчислення в запитах

Все в коді працює.
Може у кого є свіжий погляд, що явно можна оптимізувати, якщо я недогледів.

Стосовно locate() знайду час - сам перевірю, чи можна так складати запит: IF( LOCATE(' '+@inX+' ', @inTXT)=0, ...
саме у частині ' '+@inX+' ' і без використання concat(). Якщо виявиться, що так не можна, ото і буде питання.
Бо це не JavaScript і досі плутаюсь в інтерпритаторі SQL.


При деяких експериментах питання ще будуть.