Имя: Пароль:
1C
1C 7.7
v7: Как склеить запросом несколько строк в одну, на примере таблицы 1SConst
0 FobusVGrunt
 
01.06.16
11:36
Строки > 23  в таблице 1SCons хранятся блоками, номер блока в колонке «PARTNO». Как в запросе выбрать все в одну строку, склеить:
OBJID|   ID     |   DATE      |  PARTNO   |  VALUE
1        11T6     20160601       0          Привет
1        11T6     20160601       1          Как
1        11T6     20160601       2          дела?

Получить в одну строку VALUE = «Привет как дела?», если это длинная строка.
1 Heckfy
 
01.06.16
11:40
Никак.
2 f_vadim
 
01.06.16
11:45
3 Heckfy
 
01.06.16
11:50
(2) Это ни "Как". Это изврат. :)
4 YurAnt
 
01.06.16
11:58
была немного похожая задача, с тем отличием что значения были в трех разных колонках. Решал через пакет запросов.

т.е. к примеру по группировке ID=11T6

NULL   NULL  дела?
Привет  NULL  NULL
NULL   как   NULL

Запросом 1 выбирал максимум по каждому столбцу
затем Запросом 2 уже крутил вертел то что схлопнулось.

Но у меня было жестко заданное кол-во записей в группировке
5 FobusVGrunt
 
01.06.16
11:59
(2) Можно определять макс. число в поле PARTNO, и фигачить вложенные запросы к значение к полю,типа:
...
,((select ...Where PARTNO = 1) + (select ...Where PARTNO = 2)+... ) as VALUE
FROM
.....
Но не думаю, что нормальный подход с точки зрения производительности
6 Fragster
 
гуру
01.06.16
12:00
т.е. склеить во встроенном языке вообще не вариант?
7 FobusVGrunt
 
01.06.16
12:02
(6) Почему вариант в ТаблицуЗначения загнать и перебрать её. Просто интересно стало в запросе можно ли
8 FobusVGrunt
 
01.06.16
12:11
Если такой вариант:
    ТекстЗапроса = "Select
    |OBJID
    |,ID
    |,DATE
    |,CASE  (select Max(PARTNO) FROM [_1S.Const] where id = t.ID  and date = t.Date and objid = t.OBJID)
    |WHEN 0 THEN VALUE
    |WHEN 1 THEN VALUE + (select VALUE FROM [_1S.Const] where id = t.ID  and date = t.Date and objid = t.OBJID and PARTNO = 1)
    |WHEN 2 THEN VALUE + (select VALUE FROM [_1S.Const] where id = t.ID  and date = t.Date and objid = t.OBJID and PARTNO = 1)
    |+ (select VALUE FROM [_1S.Const] where id = t.ID  and date = t.Date and objid = t.OBJID and PARTNO = 2)
    |... и т.д.
    |END AS [VALUE]
    |FROM  [_1S.Const] as t
    |";
9 FobusVGrunt
 
01.06.16
12:11
(8) С точки зрения производительности?
10 YurAnt
 
01.06.16
12:13
кол-во PARTNO ограничено? или их может быть сколь угодно?
11 FobusVGrunt
 
01.06.16
12:14
(10) макс строка задать можно 999 символов, значит 999/23 = 43. Т.е. PARTNO  ограниченно 43.
12 FobusVGrunt
 
01.06.16
12:17
(10) Но вообще можно узнать макс PARTNO по всей таблицы и динамически сформировать текст запроса.
13 youalex
 
01.06.16
12:22
DECLARE @s varchar(max) = ''

SELECT @s = @s + PARTNO
FROM  [_1S.Const] as t

SELECT @s
14 YurAnt
 
01.06.16
12:23
так или иначе вариант решения сводится к выборке строк в уже заготовленные колонки - с последующим сворачиванием в 1 строку.

суть думаю примерно та же что и в (8)

Как вариант динамически собрать сам текст запроса.
зашить добавление каждой колонки запроса в зависимости от кол-ва строк, и по итогу исполнить.
это будет быстрее и производительнее нежели в цикле насиловать запросом базу построчно и собирать итоговую строку
15 YurAnt
 
01.06.16
12:25
(14) хотя будет ли это быстрее чем решение в лоб: выбрать все и в цикле сформировать по результатам выборки строку... хз
16 FobusVGrunt
 
01.06.16
12:28
(8) А еще походу в этом запросе обязательно в конце:
  |... FROM  [_1S.Const] as t Добавить - where PARTNO = 0
так как PARTNO > 0 лопатить не надо, они вложенными выбираются.
17 FobusVGrunt
 
01.06.16
13:07
Кому интересно по скорости запроса в (8), при MAX(PARTNO) = 4:
Время в милисекундах
1) Запрос в (8)  -Время:2737, Кол строк:135911
2) Обычный запрос -"Select * FROM [_1S.Const]" - время:1924, Кол строк:165517
Т.е.  всего на 42 % медленнее.
Думаю запрос в (8)оптимальный. Дольше будет циклом перебирать ТЗ.
18 FobusVGrunt
 
01.06.16
13:09
(8) Запрос на SQLIte, поэтому вместо "+", нужно "||" для склеивания строк. если стоит "+" или "&", возвращает "0". А то не мог понять в чем дело, выдавало 0.Может кому полезно будет эта инфа
19 FobusVGrunt
 
01.06.16
13:10
(13) Тут не совсем понятно, что имеется ввиду
20 FobusVGrunt
 
01.06.16
13:10
(1) Получается можно. а не "Никак"
21 youalex
 
01.06.16
14:07
(19) это для ms, на sqlite не взлетит. смысл в том, что к переменной @s - добавляется значение PARTNO каждой строки , получаемой в Select.
22 Djelf
 
01.06.16
14:33
А про GROUP_CONCAT забыли?
Ну у меня PARTNO почти нет чтобы проверить, но что-то склеивается....

SELECT
GROUP_CONCAT(PARTNO,' ')
FROM (
SELECT
OBJID
,ID
,DATE
,VALUE
,PARTNO
FROM  [_1S.Const] as t
ORDER BY OBJID,ID,DATE,PARTNO
)
GROUP by OBJID
23 Ёпрст
 
01.06.16
14:34
(18) для запроса на 1sйlite таким извратом не нужно заниматься вооообщееее, там поля неогр длины "читаются" из коробки, просто как поле в запросе.

А так, в 1sqlite есть еще group_concat, если чё
24 FobusVGrunt
 
01.06.16
14:53
(23) Так в самой таблице ДБФ 1SConst, они лежат кусками
25 FobusVGrunt
 
01.06.16
14:53
(22) А что делает GROUP_CONCAT ?
26 Djelf
 
01.06.16
15:09
(25) Клеит ;)
Для sqlite GROUP_CONCAT(ЧтоСклеиваем,Разделитель=",")
27 FobusVGrunt
 
01.06.16
15:19
(26)  В моём случаи клеить надо VALUE, а не PARTNO и клеить надо с условиями, что бы полное совпадение строк (OBJID,ID,DATE), а PARTNO разные
28 Djelf
 
01.06.16
15:25
(27) ну в (22) только и осталось что поменять VALUE на PARTNO, это я очепятался...
29 FobusVGrunt
 
01.06.16
15:58
(28) я подставлял VALUE, не понимаю как она  и что склеивает, но что работает в 3 раза дольше и результат не понятен мне, в моем запросе быстрее и все как надо. Но хотелось разобраться с  GROUP_CONCAT. Что-то не получается с  GROUP_CONCAT получить одну строку с колонками:
OBJID|   ID     |   DATE      |  PARTNO   |  VALUE
1        11T6     20160601       0          Привет как дела
как описано в (0)
30 AMKahm
 
01.06.16
16:15
(29) ну так в (22) все есть, только нафиг PARTNO=0 нужен? его отбросить надо, или тоже в '0 1 2' клеить

SELECT
     OBJID,ID,DATE,GROUP_CONCAT(VALUE,' ')
FROM
     (SELECT OBJID,ID,DATE,VALUE
      FROM 1SConst
      ORDER BY OBJID,ID,DATE,PARTNO
     )
GROUP
     OBJID,ID,DATE;
31 FobusVGrunt
 
01.06.16
16:21
(30)  PARTNO отбросить
32 FobusVGrunt
 
01.06.16
16:38
Всем спасибо разобрался GROUP_CONCAT, Выдает то что надо, но работает в 2,5 раза медленней, чем (8). Хотя конечно текст запроса в разы проще. Еще раз всем огромное спасибо
33 Ёпрст
 
01.06.16
16:51
(24) ну и что ?
34 Mikeware
 
01.06.16
16:52
(33) а как же лыжи, гамак...?
35 ДенисЧ
 
01.06.16
16:54
36 FobusVGrunt
 
01.06.16
16:58
(33) "там поля неогр длины "читаются" из коробки" не совсем понятно, что имеется ввиду.
37 Ёпрст
 
01.06.16
17:09
(36)
просто селект поле из справочник, например. Ну а в константах, так вообще не понятно, зачем там хранить такие значения.
38 Ёпрст
 
01.06.16
17:10
периодика что ле ? Еще и неогр длины ?
39 FobusVGrunt
 
01.06.16
17:25
(38) Переодичку, не ограниченной длины нельзя задать. поле VALUE в 1SConst длиной 23, может и название организации быть > 23, вот оно и разбивает на блоки. мне надо запрос к этой таблице, а не через справочники вытягивать данные. Делаю выгрузку загрузку, решил что проще переодические реквизиты и константы загрузить одним махом, а не через справочники гонять
40 Ёпрст
 
01.06.16
17:40
(39) А откуда куда ?
41 FobusVGrunt
 
01.06.16
17:41
42 Ёпрст
 
01.06.16
17:44
(41) неудачное решение.
Как будешь пасти измененные объекты ?
43 FobusVGrunt
 
01.06.16
17:51
(42) Задача измененных пасти нету. Эта пару переносов с одной базы в другую пустую с кое какими манипуляциями в новой в момент переноса. Пасти надо только новые объекты, для этого есть таблицы соответсвия по внутрений ID старой БД и новой в файле обмене (БД на SQLIte).
44 FobusVGrunt
 
01.06.16
17:58
(42) Почему не удачное решение, надо выгрузить данные куда-то и потом загрузить откуда-то. Можно это в текстовый файл выгрузить, но я выбрал формат БД Sqlite. По мне лучше чем строки разбирать
45 FobusVGrunt
 
01.06.16
18:05
(42) Да и при желании, можно и измененные объекты пасти. Перед следующей выгрузкой сравнивать, что лежит в БД Sqlite по реквизитам(полям) и помечать на обновление, если хоть один изменился, это на случай если понадобится, не лучший вариант, но повторюсь выгрузки одноразовые по разным клиентам с разными конфигурациями. Поэтому пасти изменения в старой БД например перехватчикомСобытий ни надо.
46 Djelf
 
01.06.16
23:02
Ну медленнее... ну и что? Да, там сначала упорядочивание, а потом группировка, а в твоем многоэтажном запросе подзапросы... Зато универсален. Запусти с максимальным количеством подзапросов 43 и будет уже не так весело.

Если хочется скорости можешь попробовать 1sqlite на движке 3.8.11.1 https://cloud.mail.ru/public/BRyV/g4MiSvgqz
Сортировка и группировка там на b-tree, она примерно в 3 раза быстрее для этого конкретного случая.
47 FobusVGrunt
 
02.06.16
08:49
(46) ок спасибо!
48 Djelf
 
06.06.16
17:51
Можно запрос и посложнее.
Всего раза в 2 медленнее чем без склейки длинных строк.

SELECT
    t4.ID,t4.OBJID,t4.DATE,t4.TIME,t4.VALUE
FROM  [_1S.Const] as t4
LEFT JOIN
    (SELECT
        ID,OBJID,DATE,TIME,max(PARTNO) AS maxPARTNO,VALUE
    FROM  [_1S.Const] as t
    WHERE PARTNO>0
    GROUP by ID,OBJID,DATE,TIME) as t5
    ON t4.ID=t5.ID AND t4.OBJID=t5.OBJID AND t4.DATE=t5.DATE AND t4.TIME=t5.TIME
WHERE t5.ID IS NULL

UNION ALL
SELECT
    t3.ID,t3.OBJID,t3.DATE,t3.TIME,GROUP_CONCAT(t3.VALUE) AS VALUE
FROM
    (SELECT
        t2.ID,t2.OBJID,t2.DATE,t2.TIME,t2.PARTNO,t2.VALUE
        FROM  
        (SELECT
            ID,OBJID,DATE,TIME,max(PARTNO),VALUE
        FROM  [_1S.Const] as t
        WHERE PARTNO>0
        GROUP by ID,OBJID,DATE,TIME) as t1
        LEFT JOIN [_1S.Const] as t2
            ON t1.ID=t2.ID AND t1.OBJID=t2.OBJID AND t1.DATE=t2.DATE AND t1.TIME=t2.TIME
        ORDER BY t2.ID,t2.OBJID,t2.DATE,t2.TIME,t2.PARTNO
    ) as t3
GROUP BY t3.ID,t3.OBJID,t3.DATE,t3.TIME