SQLinfo.ru - Все о MySQL

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

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

Вы не зашли.

#1 12.04.2011 16:37:50

maxist
Участник
Зарегистрирован: 12.04.2011
Сообщений: 5

Не циклический запрос

Итак, есть таблица

create table t1 (`id` not null auto_increment, `doc_num` varchar(10), `date` date, primary key(`id`))


в поле doc_num хранятся строки вида:
8888
8888/1
8888/2
8889
8889/1
8889/2


То есть возможно простое число, и возможно число с дробью.
Теперь есть запрос
select id,doc_num from t1 where doc_num not like '%/%' and date(date)=date(now())

Этим запросом я получаю doc_num без дробей для этого дня.

Дальше в цикле php перебираю полученный результат и высчитываю количество совпадений с этим номером:

while ($row = $res->fetch_assoc()){

$query = 'select count(*) from t1 where doc_num like "'.$row['doc_num'].'%" and date(date)=date(now())';

// Если результат запроса равен 1 (то есть такое число было один раз) то делается прерывание цикла и выводится этот номер (Если число попалось один раз - то это точно число без дроби)
}




По поводу оптимизации. в таблице стоят ключ на поле date и в запросах участвуют date between.
Во втором запросе выражение date(date)=date(now()) нужно для того, что каждый месяц doc_num считается заново.

Вот вопрос

как объединить эти два запроса? В цикле хорошо загружается mysql сервер. Что есть для меня плохо.

Если ли в mysql динамические переменные? Чтобы сделать запрос вида -

select tt1.id,tt1.doc_num, select count(*) from t1 where doc_num like concat(tt1.doc_num,"%") and date(date)=date(now()) as @@P1 from t1 tt1 where @@P1 <3 and tt1.doc_num not like '%/%' and date(tt1.date)=date(now())


Где @@P1 присваивается значение select
Суть запроса - вывести табличку, с номеров документов где количество каждого номера doc_num будет меньше 3.

чтобы был результат вида:

id | doc_num | @@P1
---------------------
1  |       2222|       1
2  |       2223|       2
3  |       2224|       1 

То есть в таблице значение doc_num = 2222 или =2224 повторяется один раз и без дробей. а номер 2223 повторяется один раз без дроби и один раз с дробью...

Хочется все объединить в один запрос.
Надеюсь поймете что пытался донести

Отредактированно maxist (12.04.2011 16:43:34)

Неактивен

 

#2 12.04.2011 21:15:49

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Не циклический запрос

1. Ужасно неудачная организация хранения данных. Нельзя разбить на два
поля целочисленных? Кажется, все запросы упростятся в разы.

2. Если оставаться со строками, то попробуйте написать осмысленное выра-
жение через LOCATE() / LEFT() — Вас же интересует группировка по левой
части строки.

3. В случае строк — не найдейтесь на то, что оно сможет работать хоть когда-
либо хоть сколь-либо быстро.

4. Да, переменные есть (только один символ @ нужен).

Неактивен

 

#3 13.04.2011 16:21:11

vaspet
Завсегдатай
Зарегистрирован: 11.03.2009
Сообщений: 83

Re: Не циклический запрос

бяка, конечно. Но, пардон: какая задача - такой ответ. Не обессудте.


SELECT
  t1.doc_num, count(*)
FROM
  temp as t1
inner join
  temp as t2
on
  LOCATE("/", t1.doc_num) = 0
AND
(
     t1.doc_num = t2.doc_num
    OR
     t1.doc_num = LEFT(t2.doc_num, LOCATE("/", t2.doc_num)-1)
)
GROUP BY
  t1.doc_num



Кстати, что лучше?:
LOCATE("/", t1.doc_num) = 0
или
t1.doc_num NOT LIKE "%/%"

Неактивен

 

#4 13.04.2011 16:50:28

maxist
Участник
Зарегистрирован: 12.04.2011
Сообщений: 5

Re: Не циклический запрос

Что-то мне кажется этот запрос будет сильно весомым... Перебор каждая с каждой. Правда за идеи спасибо. Сейчас еще прочту документацию

Неактивен

 

#5 15.04.2011 21:05:06

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Не циклический запрос

2vaspet: моя интуиция меня подвела, я думал, что наоборот smile

Код:

[silentia] root (none) > select benchmark(1000000,@a like '%/%');
+----------------------------------+
| benchmark(1000000,@a like '%/%') |
+----------------------------------+
|                                0 |
+----------------------------------+
1 row in set (0.51 sec)

[silentia] root (none) > select benchmark(1000000,LOCATE("/", @a));
+------------------------------------+
| benchmark(1000000,LOCATE("/", @a)) |
+------------------------------------+
|                                  0 |
+------------------------------------+
1 row in set (0.70 sec)

Неактивен

 

Board footer

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