Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Составление SQL-запросов > аналог sum для строк


Автор: Kbl4AH 12.2.2009, 10:59
Добрый день.
table:
STR | INT
-----------
q     | 1
w    | 2
e     | 1
r     | 1
t     | 2
y     | 1

Нужно выбрать значения поля STR, для которых I = const, но чтобы результат был не
STR
-----
rec1
...
recN

, а
STR
-----
rec1 || ... || recN

Например, для выбора STR where INT = 1, результат:
STR
-----
qery

Возможно это?

Автор: Zloxa 12.2.2009, 11:05
oracle 6?

Автор: Akina 12.2.2009, 11:17
В некоторых диалектах есть функции конкатенации строк для группы (скажем в mySQL это group_concat), в некоторых нет. 
В тех, где этого нет, для получения такого результата возможно использование хранимых процедур. Опять-таки если оно есть.

Автор: v2v 12.2.2009, 11:23
Для Оракла SYS_CONNECT_BY_PATH (Это кажется мне как раз Zloxa  и подсказал когда то smile ) либо своя Pl/Sql функция



Автор: Kbl4AH 12.2.2009, 12:02
Цитата(Zloxa @  12.2.2009,  11:05 Найти цитируемый пост)
oracle 6?

Угу :(
Я, конечно, эту проблему уже средствами Делфи обошел...
Но вопрос интересный, поэтому хочется услышать решение, не обязательно для 6-ки, а для любой удобной версии...

Добавлено через 1 минуту и 9 секунд
Цитата(Akina @  12.2.2009,  11:17 Найти цитируемый пост)
скажем в mySQL это group_concat

круто smile 

Автор: Zloxa 12.2.2009, 12:43
Цитата(Kbl4AH @  12.2.2009,  12:02 Найти цитируемый пост)
для любой удобной версии.

9i+
1) Единственный честный способ - http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14289/dciaggfns.htm#sthref566. Требует создания объектов схемы, что не всегда возможно.
http://asktom.oracle.com/pls/asktom/f?p=100:11:132921812165416::::P11_QUESTION_ID:229614022562#tom2081176199386

2) не честный через sys_connect_by_path
Код

SQL> with t as (
  2    select 'q' str, 1 int from dual
  3    union all select 'w' str, 2 int from dual
  4    union all select 'e' str, 1 int from dual
  5    union all select 'r' str, 1 int from dual
  6    union all select 't' str, 2 int from dual
  7    union all select 'y' str, 1 int from dual)
  8  select replace(max(sys_connect_by_path(str,'~')),'~') sumstr,int
  9    from (select row_number() over (partition by int order by null) rn
 10                , t.*
 11          from t) t
 12  start with rn = 1
 13  connect by prior int = int and prior rn = rn -1
 14  group by int
 15  ;
 
SUMSTR            INT
---------- ----------
qery                1
tw                  2


3) нечестный вариант - через преобразование в XML
(можно потерять лидирующие и завершающие пробелы)
Код

 15  select dbms_xmlgen.convert(xmlagg(XMLElement("a",str) /*order by ???*/).extract('//a/text()').GetStringVal(),1) sumstr
 16    ,int
 17  from t group by int
 18  ;
 
SUMSTR            INT
---------- ----------
qeyr                1
wt                  2


10g
4) нечестный вариант -  использовать недокументированную функцию wm_concat
можно потерять запятые, нельзя указать порядок внутренней сортировки
Код

  8  select replace(wm_concat(str),',') sumstr, int
  9  from t
 10  group by int
 11  ;
 
SUMSTR            INT
---------- ----------
qeyr                1
wt                  2


Наверное есть еще способы smile

Автор: Kbl4AH 12.2.2009, 13:03
Спасибо, Zloxa.
+1 за исчерпывающий ответ!
Варианты для 9ки и XML для меня пока сложноваты...
А для 10ки - понравился, запомню на будущее...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)