Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Выборка одной и той же строки несколько раз
Форумы портала PHP.SU » PHP » SQL и Архитектура БД » Выборка одной и той же строки несколько раз

Страниц (1): [1]
 

1. Slavenin - 19 Мая, 2011 - 20:27:09 - перейти к сообщению
Всем доброго времени суток!

Возникла такая необходимость, есть n строк в бд в которых содержится информация о некоторых вещах и их количестве. Необходимо выбрать каждую строку столько раз, сколько содержится в количестве. Т.е. есть строки

id | название | количество
1 | вещь1 | 4
2 | вещь2 | 3

необходимо строку 1 выбрать четыре раза, а строку 2 - три раза, одним запросом, причем количество строк может быть разным в зависимости от условия. Нужно реализовать это на чистом sql без использования php или javascript.
Нужно это чтобы выводилось типа вещь1 1 из 4, вещь1 2 из 4 и тд.
Подскажите направление в котором думать, уже сломал весь мозг себе.
2. DeepVarvar - 19 Мая, 2011 - 20:38:44 - перейти к сообщению
Slavenin пишет:
на чистом sql без использования php или javascript

Покажите как вы на javascript ЭТО делаете!!!

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT t.*,COUNT(t.*) cnt1,tt.*,COUNT(tt.*) cnt2 FROM t LEFT JOIN t tt WHERE t.id = 1 AND tt.id = 2

Не проверял... Ниндзя
3. Slavenin - 19 Мая, 2011 - 20:46:48 - перейти к сообщению
[quote=DeepVarvar]
Slavenin пишет:
на чистом sql без использования php или javascript

Покажите как вы на javascript ЭТО делаете!!!

я имею в виду, что выборку строк можно сделать запросом, а обработчик написать в виде цикла на php либо ajax запросом и циклом уже на java

неа, не получается таким запросом
пишет ошибку

Цитата:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '*) cnt1,tt.*,COUNT(tt.*) cnt2 FROM t_items as t LEFT JOIN t tt WHERE t.i_code = ' at line 1


запрос:

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT t.*,COUNT(t.*) cnt1,tt.*,COUNT(tt.*) cnt2 FROM t_items AS t LEFT JOIN t tt WHERE t.i_code = 'item1'
4. DeepVarvar - 19 Мая, 2011 - 21:10:19 - перейти к сообщению
Дайте реальные имена таблицы и полей
5. Slavenin - 19 Мая, 2011 - 21:17:17 - перейти к сообщению
таблица t_items
поле имени i_code
поле количества i_count
6. DeepVarvar - 19 Мая, 2011 - 21:32:48 - перейти к сообщению
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT t_items.id,t_items.i_code,t_items.i_count,t_items2.id id2,t_items2.i_code i_code2,t_items2.i_count i_count2 FROM t_items LEFT JOIN t_items t_items2 ON (t_items2.id = (t_items.id+1)) WHERE t_items.id = 1
7. Slavenin - 19 Мая, 2011 - 21:52:00 - перейти к сообщению
поля id в таблице нет, ключом является поле i_code(varchar). Выбрать нужно именно несколько копий одной строки , а не присоединить копию слева
8. DeepVarvar - 19 Мая, 2011 - 21:58:08 - перейти к сообщению
Тогда мне кажется что задача несколько маразматична - множить результат для вывода...
9. Slavenin - 19 Мая, 2011 - 22:02:51 - перейти к сообщению
есть такая волшебная программа зовется bartender печатает она этикетки, настройка функции сериализации в ней не позволяет сделать вывод этикеток в нужном формате, зато она умеет работать с базой. поэтому для реализации задачи, необходимо именно размножить вывод нужное количество раз
10. DeepVarvar - 19 Мая, 2011 - 22:20:59 - перейти к сообщению
А вот теперь интересно Улыбка
Так тем же джойном, только убрать +1 в запросе..
И далее сколько раз надо, столько и джойнить..
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT t_items.i_code,t_items.i_count
  2. t_items2.i_code i_code2,t_items2.i_count i_count2,
  3. t_items3.i_code i_code3,t_items3.i_count i_count3,
  4. t_items4.i_code i_code4,t_items4.i_count i_count4
  5. FROM t_items
  6. LEFT JOIN t_items t_items2 ON (t_items2.i_code = t_items.i_code)
  7. LEFT JOIN t_items t_items3 ON (t_items3.i_code = t_items.i_code)
  8. LEFT JOIN t_items t_items4 ON (t_items4.i_code = t_items.i_code)
  9. WHERE t_items.i_code = 'чему_оно_там_равно'

Наверное есть какое-то более лаконичное решение..
11. EuGen - 20 Мая, 2011 - 11:19:13 - перейти к сообщению
Лаконичнее - вряд ли.
Ваше плохо тем, что если надо на чистом SQL, то мы не знаем, сколько заранее раз надо выполнять JOIN. Плюс к тому если повторять надо раз 500, JOIN уже не кажется таким уж отличным решением.
В качестве "классического" SQL-решения мне тоже не удалось найти ничего.
Однако можно использовать SQL-процедуры, которые по сути повторят ту же работу, что была бы проделана в скрипте. Вот то, что сделал я:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. DROP PROCEDURE IF EXISTS dorepeat;
  3.  
  4. delimiter //
  5.  
  6. CREATE PROCEDURE dorepeat()
  7. BEGIN
  8.    SET @i=0;
  9.    SET @c=(SELECT COUNT(*) FROM `repeats`);
  10.    SET @s='';
  11.    REPEAT      
  12.       PREPARE repsel FROM 'SELECT num INTO @r FROM repeats LIMIT ?,1';
  13.       EXECUTE repsel USING @i;
  14.       PREPARE repsel FROM 'SELECT id INTO @id FROM repeats LIMIT ?,1';
  15.       EXECUTE repsel USING @i;
  16.       SET @j=0;
  17.       REPEAT
  18.          SET @s=CONCAT(@s, 'SELECT ',@id,' UNION ALL ');
  19.          SET @j=@j+1;
  20.       UNTIL @j>@r-1 END REPEAT;
  21.       SET @i=@i+1;    
  22.    UNTIL @i>@c-1 END REPEAT;
  23.    SET @s=SUBSTRING(@s, 1, LENGTH(@s)-10);  
  24.    PREPARE mainsel FROM @s;
  25.    EXECUTE mainsel;
  26.    DEALLOCATE PREPARE mainsel;
  27. END
  28. //
  29. delimiter ;
  30.  

Таблица:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. CREATE TABLE `repeats` (
  3.  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  4.  `num` int(11) UNSIGNED NOT NULL,
  5.  PRIMARY KEY  (`id`)
  6. ) ENGINE=InnoDB;
  7.  

После определения нужно вызывать процедуру так:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. call dorepeat;
  3.  
12. EuGen - 20 Мая, 2011 - 13:59:39 - перейти к сообщению
Придумал как сделать на "чистом" SQL:
Если создать дополнительную таблицу такого вида:
CODE (SQL):
скопировать код в буфер обмена
  1. CREATE TABLE `natural` (
  2.  `id` int(11) UNSIGNED NOT NULL,
  3.  PRIMARY KEY  (`id`)
  4. ) ENGINE=InnoDB

И заполнить её значениями целых положительных чисел подряд (в моем примере я заполнил ее от 1 до 10)
То выбрать строки можно так:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT repeats.* FROM `natural` LEFT JOIN repeats ON `natural`.id<=repeats.num WHERE repeats.id IS NOT NULL
  3.  

Таблица repeats та же.
Стоит отметить, что таблица naturals должна быть заполнена до значения, которое больше максимального числа повторений из таблицы repeats.
13. Sylver - 02 Февраля, 2016 - 09:51:19 - перейти к сообщению
Тоже озаботился повторением этикеток в Bartender, придумал вот такое решение для размножения этикеток, позволяет вставить на этикетку поле заполняемое для каждой новой записи из БД.


CODE (SQL):
скопировать код в буфер обмена
  1. SELECT
  2.         (SELECT 'одна запись' FROM dual) AS str
  3. FROM dual
  4. connect BY rownum <= 'сколько надо повторить'
  5.  

 

Powered by ExBB FM 1.0 RC1