Kaer_Morchen
@Kaer_Morchen
Разрабатываю web-приложения.

SQL запрос с выборкой id из списка?

Всем привет.

БД MySql.

Имеется таблица вида:
CREATE TABLE `test` (
	`id` INT(11) NULL DEFAULT NULL,
	`value` INT(11) NULL DEFAULT NULL
)


id        |         value
------------------------------------
   1                     10
   2                     15
   3                     23

Мне нужно получить сумму value, id из списка например - "1, 1, 2".

Проблема в том что есть дублирования id. И просто добавить условие с WHERE IN не выйдет.

По идее можно создавать временную таблицу в памяти, присоединить и просуммировать нужные поля, но может быть у кого то есть более быстрое и верное решение?

Update:
Такой запрос НЕ правильный:
SELECT SUM(value) FROM test WHERE id IN (1, 1, 2);

Update 2:
Список id это внешние данные, с учетом которых нужно получить сумму полей value.

Если взять список id: 1, 1, 2
То запрос должен вернуть 35 (10 + 10 + 15)
  • Вопрос задан
  • 12947 просмотров
Решения вопроса 2
profit
@profit
Разработка | Оптимизация. Telegram: @evzavyalov
как вариант... собрать 1,1,2 в
select 1 id union all select 1 id union all select 2 id

и при-JOIN-ить
select sum(value) 
  from test t
     , (select 1 id union all select 1 id union all select 2 id) tab
 where t.id = tab.id
Ответ написан
Комментировать
Immortal_pony
@Immortal_pony Куратор тега MySQL
Мне кажется, что данную задачу лучше решать на языке программирования, но уж если очень хочется посчитать данные прямо в базе, то можно написать процедуру
DELIMITER $$

USE `test`$$

DROP PROCEDURE IF EXISTS `get_summed_data`$$

CREATE PROCEDURE `get_summed_data`(IN ids TEXT)
BEGIN	
	DECLARE iterator INT;
	DECLARE number_of_ids INT;
	DECLARE id_start_position INT;
	DECLARE id_end_position INT;
	DECLARE test_value INT;
	
	
	DROP TEMPORARY TABLE IF EXISTS `tmp_get_summed_data_ids`;
	CREATE TEMPORARY TABLE `tmp_get_summed_data_ids` (
		`id` INT(11) NULL DEFAULT NULL,
		`value` INT(11) NULL DEFAULT NULL
	);
	
	SET number_of_ids = ROUND((LENGTH(ids) - LENGTH(REPLACE(ids, ",", ""))) / LENGTH(","))+1;   
	SET iterator = 0;
	SET id_start_position = 1;
	
	WHILE (iterator < number_of_ids) DO		
		SET id_end_position = CASE 
			WHEN (LOCATE(',', ids, id_start_position) > 0) THEN
				LOCATE(',', ids, id_start_position)
			ELSE 
				LENGTH(ids)+1
		END;		
		SET @id = SUBSTRING(ids, id_start_position, id_end_position-id_start_position);
		SET test_value = (SELECT `value` FROM `test` WHERE `id` = @id);
		
		INSERT INTO `tmp_get_summed_data_ids` VALUES (@id, test_value);
		
		SET id_start_position = id_end_position+1;
		SET iterator = iterator+1;
	END WHILE;
	
	SELECT SUM(`value`) AS 'sum' FROM `tmp_get_summed_data_ids`;
END$$

DELIMITER ;


Вызывать так:
CALL get_summed_data('1,1,2');
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
DmitriyEntelis
@DmitriyEntelis
Думаю за деньги
С учетом Update 2 - imho самое правильное решение это выбирать value из базы where in и суммировать в ЯП.
Ответ написан
Комментировать
flashg
@flashg
SELECT id, SUM(value) FROM test GROUP BY id
Ответ написан
HaJIuBauKa
@HaJIuBauKa
Это в лоб так сказать
--SELECT SUM(select value from test t2 where t2.id=t1.id) FROM test t1 WHERE id IN (1, 1, 2);

select sum(val1) from (SELECT (select value from test t2 where t2.id=t1.id) val1 FROM test t1 WHERE id IN (1, 1, 2));
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы