powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Объединение строк
26 сообщений из 26, показаны все 2 страниц
Объединение строк
    #40016867
Nevillested
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго времени суток, форумчане.
Видел уже множество тем на этом форуме по объединению строк, с помощью group_by, xml path, string_agg, но так и не получилось выродить у меня решение моей проблемы.
Прошу прощения, но к сожалению пришлось-таки создать топик.
К сути:
Есть огромное множество строк в таблице, среди них 4 (допустим) строки принадлежат одному человеку. То есть, в одной строке имеется ФИО, в другой строке имеется почта, в третьей строке имеется телефон, в четвертой-клиент айди (клиент айди имеется у всех четырех строк). При этом, те значения, которых нет в какой-либо строке это NULL.
Нужно все четыре строки объединить в одну, при этом клиент айди сделать такой, который был в самой первой строке.

И так во всей таблице.
Например как в скриншоте. (который я не вижу чтобы загрузился)
Версия sql 17
...
Рейтинг: 0 / 0
Объединение строк
    #40016869
Oleg_SQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Nevillested, а где скриншот?

Ну по всей логике сначала нужно построить таблицу со всеми возможными столбцами, а затем уже заполнить ее.
Таблица может быть временной ))
...
Рейтинг: 0 / 0
Объединение строк
    #40016870
Nevillested
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Oleg_SQL,
Скриншот не получается по каким-то причинам прикрепить.Тогда приведу пример в текстовом виде:
Имеется такое:

Код: plsql
1.
2.
3.
4.
5.
client_id | name | phone | e-mail 
1         | Иван |       | i@iv.ru
2         |      | 99999 |
3         | Иван |       | i@iv.ru
4         |      | 99999 | i@iv.ru



Необходимо получить:

Код: plsql
1.
2.
client_id | name | phone | e-mail 
1         | Иван | 99999 | i@iv.ru
...
Рейтинг: 0 / 0
Объединение строк
    #40016871
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nevillested,

Например как в скриншоте. (который я не вижу чтобы загрузился)


на нет и суда нет.
ваше описание задачи слишком размытое, прикладывайте тестовые данные и результат который хотите получить.

add: опередили третьим постом.

ну в таком случае как должен выглядеть результат вот с такими данными ?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
client_id | name | phone | e-mail 
1         | Иван |       | i@iv.ru
2         |      | 99999 |
3         | Иван |       | i@iv.ru
4         |      | 99999 | i@iv.ru
5       | Андрей |       | i@iv.ru
7       |  Денис |       | 
8       |        | 8888  | b@iv.ru
9       |        | 9999  | c@iv.ru
...
Рейтинг: 0 / 0
Объединение строк
    #40016872
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nevillested
Oleg_SQL,
Скриншот не получается по каким-то причинам прикрепить.Тогда приведу пример в текстовом виде:
Имеется такое:

Код: plsql
1.
2.
3.
4.
5.
client_id | name | phone | e-mail 
1         | Иван |       | i@iv.ru
2         |      | 99999 |
3         | Иван |       | i@iv.ru
4         |      | 99999 | i@iv.ru




Необходимо получить:

Код: plsql
1.
2.
client_id | name | phone | e-mail 
1         | Иван | 99999 | i@iv.ru



А как тоже самое будет выглядеть на нескольких клиентах?
Какие правила деления записей на отдельных клиентов?
...
Рейтинг: 0 / 0
Объединение строк
    #40016873
Nevillested
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff,
Сообщение выше не подойдет?
...
Рейтинг: 0 / 0
Объединение строк
    #40016875
Nevillested
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
msLex,
Я думаю, что можно было бы это сделать по условию совпадения, если фио/дата рождения/почта совпадают, то это 1 клиент
Например, если есть три строки, в которых есть одна и та же почта-схлопнуть их в одну. Или же если почты нет, а есть одинаковый телефон-также объединить в одну строку.
Ну или ФИО+дата рождения (хотя даже в таком случае могут существовать несколько человек с такими же ФИО+дата рождения, поэтому такой вариант не подойдет скорее всего)
...
Рейтинг: 0 / 0
Объединение строк
    #40016876
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nevillested
msLex,
Я думаю, что можно было бы это сделать по условию совпадения, если фио/дата рождения/почта совпадают, то это 1 клиент
Например, если есть три строки, в которых есть одна и тоже почта-схлопнуть их в одну. Или же если почты нет, а если телефон-также объединить в одну строку.
Ну или ФИО+дата рождения (хотя даже в таком случае могут существовать несколько человек с такими же ФИО+дата рождения, поэтому такой вариант не подойдет скорее всего)


А если у одного ФИО окажется несколько телефонов или email-ов?
А если к этим телефонам или email-ам привязаны другие телефоны, email-ы, ФИО?
...
Рейтинг: 0 / 0
Объединение строк
    #40016877
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nevillested,

приведите структуру таблицы и тестовые данные.

вы говорите что есть ФИО и дата рождения а приводите в виде тестовых данных какое то подобие где есть только name

идентификатор client_id у вас нифига не идентификатор, а какой то сквозной нумератор.
я пока не понимаю структуру данных хранящихся у вас в таблице.

такое впечатление что там набор строк вида
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
create table myTable (
[data] varchar(max)
);

insert into myTable ('1         | Иван |       | i@iv.ru');
insert into myTable ('2         | Иван |       | i@iv.ru');
insert into myTable ('3         | Иван |       | i@iv.ru'); 
blablabla
...
Рейтинг: 0 / 0
Объединение строк
    #40016878
Nevillested
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
msLex,
В таком случае, у этого человека будет несколько клиент_айди и это будет правильно
...
Рейтинг: 0 / 0
Объединение строк
    #40016881
Nevillested
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff,
Таблица состоит из столбцов: client_id, phone, surname, firstname, sex, date_birthday, age, city, e-mail, timezone, sum_amount
Я привел выше пример для простоты, чтобы не вдаваться в подробности и понять логику, как это сделать, но, видимо, нужно все
...
Рейтинг: 0 / 0
Объединение строк
    #40016882
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nevillested
msLex,
В таком случае, у этого человека будет несколько клиент_айди и это будет правильно


Не сомневаюсь, что это правильно, но не понимаю, как в вашей задачи это разделение происходит.

Например

Код: plaintext
1.
2.
3.
4.
5.
6.
NAME1 PNONE1 NULL
NAME2 PNONE2 NULL
NAME3 NULL EMAIL1 
NAME4 NULL EMAIL1 
NULL PHONE1 EMAIL1 
NULL PHONE2 EMAIL1


Сколько это клиентов и где чьи телефоны и email?
...
Рейтинг: 0 / 0
Объединение строк
    #40016883
Nevillested
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
msLex,
Ну в Вашем примере не совсем верно, такого примера просто не может быть, т.к. EMAIL1 не может быть одновременно сразу у NAME1, NAME2, NAME3, NAME4
Правильный пример такой:

NAME1 PNONE1 NULL
NAME2 PNONE2 NULL
NAME3 NULL EMAIL3
NAME4 NULL EMAIL4
NULL PHONE1 EMAIL1
NULL PHONE2 EMAIL2

Результат:

NAME1 PNONE1 EMAIL1
NAME2 PHONE2 EMAIL2
NAME3 NULL EMAIL3
NAME4 NULL EMAIL4


В конечном итоге, нужно чтобы эти строки объединялись по выполняемым условиям. Т.е. имеется минимальный набор условий, при которых строки объединяться, например в двух строках совпадают 4 столбца, как минимум. Например это surname, firstname, sex, date_birthday
...
Рейтинг: 0 / 0
Объединение строк
    #40016884
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nevillested
felix_ff,
Таблица состоит из столбцов: client_id, phone, surname, firstname, sex, date_birthday, age, city, e-mail, timezone, sum_amount
Я привел выше пример для простоты, чтобы не вдаваться в подробности и понять логику, как это сделать, но, видимо, нужно все


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

idnamephonemail1Вася21111@iv.ru3Петя22243332@iv.ru5Коля6Миша3@iv.ru74@iv.ru87779Юра9994@iv.ru10888

idnamephonemail1Вася1111@iv.ru3Петя222;3332@iv.ru5Коля6Миша7773@iv.ru;4@iv.ru9Юра888;9994@iv.ru

вы вот такого хотите добиться?
...
Рейтинг: 0 / 0
Объединение строк
    #40016886
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nevillested
msLex,
Ну в Вашем примере не совсем верно


Мой пример полностью укладывается в вашу структуру данных, а значит, с точки зрения возможных данных, он абсолютно верен.

Если это не какой-нибудь тестовый набор данных, генерируемый на основе изначально нормализованных данных, а данные вносимые пользователями, то подобные коллизии неизбежны. А значит вам нужно придумать некую стратегию по их корректной интерпретации.
...
Рейтинг: 0 / 0
Объединение строк
    #40016892
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nevillested
msLex,
Ну в Вашем примере не совсем верно, такого примера просто не может быть, т.к. EMAIL1 не может быть одновременно сразу у NAME1, NAME2, NAME3, NAME4
Правильный пример такой:

NAME1 PNONE1 NULL
NAME2 PNONE2 NULL
NAME3 NULL EMAIL3
NAME4 NULL EMAIL4
NULL PHONE1 EMAIL1
NULL PHONE2 EMAIL2

Результат:

NAME1 PNONE1 EMAIL1
NAME2 PHONE2 EMAIL2
NAME3 NULL EMAIL3
NAME4 NULL EMAIL4


В конечном итоге, нужно чтобы эти строки объединялись по выполняемым условиям. Т.е. имеется минимальный набор условий, при которых строки объединяться, например в двух строках совпадают 4 столбца, как минимум. Например это surname, firstname, sex, date_birthday



Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
declare @t table (
       [client_id] int,
       [name] varchar(255),
       [phone] varchar(50),
       [mail] varchar(50)
);

insert into @t values (1, 'NAME1', 'PHONE1', NULL);
insert into @t values (2, 'NAME2', 'PHONE2', NULL);
insert into @t values (3, 'NAME3', NULL,     'EMAIL3');
insert into @t values (4, 'NAME4', NULL,     'EMAIL4');
insert into @t values (5, NULL,    'PHONE1', 'EMAIL1');
insert into @t values (6, NULL,    'PHONE2', 'EMAIL2');
insert into @t values (7, 'NAME5',    'PHONE3', NULL);
insert into @t values (8, NULL,    'PHONE3', 'EMAIL5');


with clients as (
    select [client_id], [name], [phone], [mail] from @t where [name] is not null
)
select
      clients.[client_id],
      clients.[name],
      coalesce(clients.[phone], c1.[phone], c2.[phone]) as [phone],
      coalesce(clients.[mail], c1.[mail], c2.[phone]) as [mail]
from clients
    outer apply (select top(1) [client_id], [phone], [mail] from @t t where t.[client_id] > clients.[client_id] and t.[phone] = clients.[phone]) c1
    outer apply (select top(1) [client_id], [phone], [mail] from @t t where t.[client_id] > clients.[client_id] and t.[mail] = clients.[mail]) c2



и так добавляете еще кучу связей по которым могут быть совпадения
...
Рейтинг: 0 / 0
Объединение строк
    #40016907
Nevillested
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff, немного не так.
Простите меня, за мои тщетные попытки объяснить, но я попробую снова, но уже детально.
Имеется:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
client_id | firstname | surname | sex | date_birthday | age | city   |  e-mail   | timezone | sum_amount | phone
1         | Иван      | Иванов  |  м  |    01.01.72   | 48  | Moscow |           |          |            |      
2         | Ольга     |         |  ж  |    02.03.90   |     |        | ola@o.ru  |    +3    |    5000    | 22222
3         | Иван      |         |     |    01.01.72   |     |        | ivan@i.ru |    +3    |    6000    | 11111
4         | Денис     |         |  м  |    03.03.80   |     |        | den@i.ru  |          |    4000    | 33333
5         | Андрей    |         |  м  |    01.01.72   | 48  |        |           |          |            |      
7         | Денис     |         |     |               |     |        |           |    +5    |    4000    | 33333
8         | Ольга     | Олевна  |  ж  |    02.03.90   | 30  | Moscow |           |          |    5000    | 22222
9         | Иван      | Иванов  |  м  |               |     |        |           |          |    6000    | 11111


Схлопывание дублей происходит конкретно, если в двух и более строках одинаковы phone и sum_amount. В противном случае-если соответствий у одной строки с другими по phone и sum_amount не найдено, то ее не трогать и это не считается дублем.

Результат:
Код: plsql
1.
2.
3.
4.
5.
6.
client_id | firstname | surname | sex | date_birthday | age | city   |  e-mail   | timezone | sum_amount | phone
1         | Иван      | Иванов  |  м  |    01.01.72   | 48  | Moscow |           |          |            |      
2         | Ольга     | Олевна  |  ж  |    02.03.90   | 30  | Moscow | ola@o.ru  |    +3    |    5000    | 22222
3         | Иван      | Иванов  |  м  |    01.01.72   |     |        | ivan@i.ru |    +3    |    6000    | 11111
4         | Денис     |         |  м  |    03.03.80   |     |        | den@i.ru  |    +5    |    4000    | 33333
5         | Андрей    |         |  м  |    01.01.72   | 48  |        |           |          |            |      
...
Рейтинг: 0 / 0
Объединение строк
    #40016909
Nevillested
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
msLex,
Нет, эти данные не вносятся пользователями, они произрастают из другой черновой таблицы, которая проходит "очистку" определнными процессами.
...
Рейтинг: 0 / 0
Объединение строк
    #40016911
Nevillested
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff,
Большое спасибо, пока что мало что понятно, но буду сейчас пытаться разобрать Ваш код)
...
Рейтинг: 0 / 0
Объединение строк
    #40016921
godsql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Nevillested,

Тогда сделайте временную таблицу с уникальными phone и sum_amount и на основе ее, заполняйте остальные поля
...
Рейтинг: 0 / 0
Объединение строк
    #40016926
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nevillested,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
declare @t table (
       [client_id] int,
       [name] varchar(255),
       [surname] varchar(255),
       [sex] char,
       [birthday] date,
       [phone] int,
       [amount] int
);

insert into @t values (1, 'Иван',   'Иванов', 'м',  '01.01.72',  null,  null)      
insert into @t values (2, 'Ольга',  null,     'ж',  '02.03.90',  22222, 500)
insert into @t values (3, 'Иван',   null,     null, '01.01.72',  11111, 600)
insert into @t values (4, 'Денис',  null,     'м',  '03.03.80',  33333, 400)
insert into @t values (5, 'Андрей', null,     'м',  '01.01.72',  null,  null)
insert into @t values (7, 'Денис',  null,     null, null,        33333, 400)
insert into @t values (8, 'Ольга',  'Олевна', 'ж',  '02.03.90',  22222, 500)
insert into @t values (9, 'Иван',   'Иванов', 'м',  null,        11111, 600);

with clients as (
    select
          count(1) over (partition by isnull([phone], cast(newid() as varbinary(6))), [amount] order by [client_id] range between unbounded preceding and unbounded following) as [xcnt], 
          sum(1) over (partition by isnull([phone], cast(newid() as varbinary(6))), [amount] order by [client_id]) as [xrn],
          *
    from @t
)
select [client_id], [name], [surname], [sex], [birthday], [phone], [amount] from clients where [xcnt] = 1
union
select
      c1.[client_id],
      coalesce(c1.[name], cx.[name]) as [name],
      coalesce(c1.[surname], cx.[surname]) as [surname],
      coalesce(c1.[sex], cx.[sex]) as [sex],
      coalesce(c1.[birthday], cx.[birthday]) as [birthday],
      c1.[phone],
      c1.[amount]
from clients c1
    outer apply (
         select
               max(c2.[name]) as [name],
               max(c2.[surname]) as [surname],
               max(c2.[sex]) as [sex],
               max(c2.[birthday]) as [birthday]
         from clients c2  
         where c2.[phone] = c1.[phone]
           and c2.[amount] = c1.[amount]
           and c2.[xcnt] > 1
           and c2.[xrn] > 1
    ) cx
where c1.[xcnt] > 1
  and c1.[xrn] = 1
order by client_id
...
Рейтинг: 0 / 0
Объединение строк
    #40016941
godsql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
тоже работает, но если четко соблюдается наличие уникальных пар phone+amount :)

использовал таблицу от felix_ff
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
with clients as (
    select distinct phone, amount
    from @t
	where phone is not null or  amount is not null
)
select  t3.[client_id],  t3.[name],  t3.[surname],  t3.[sex],  t3.[birthday], t1.[phone], t1.[amount] from clients t1
cross apply (
select min(t2.[client_id]) as [client_id],  max(t2.[name]) as [name],  max(t2.[surname]) as surname,
  max(t2.[sex]) as sex,  max(t2.[birthday]) as [birthday] from @t t2 
where t2.[phone]=t1.[phone] and t2.[amount]=t1.[amount]
) as t3
...
Рейтинг: 0 / 0
Объединение строк
    #40017531
Nevillested
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff,
Прошу прощения, может вопрос глупый, но я так понимаю, Вы создаете таблицу и вносите туда значения:

автор
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
declare @t table (
       [client_id] int,
       [name] varchar(255),
       [surname] varchar(255),
       [sex] char,
       [birthday] date,
       [phone] int,
       [amount] int
);

insert into @t values (1, 'Иван',   'Иванов', 'м',  '01.01.72',  null,  null)      
insert into @t values (2, 'Ольга',  null,     'ж',  '02.03.90',  22222, 500)
insert into @t values (3, 'Иван',   null,     null, '01.01.72',  11111, 600)
insert into @t values (4, 'Денис',  null,     'м',  '03.03.80',  33333, 400)
insert into @t values (5, 'Андрей', null,     'м',  '01.01.72',  null,  null)
insert into @t values (7, 'Денис',  null,     null, null,        33333, 400)
insert into @t values (8, 'Ольга',  'Олевна', 'ж',  '02.03.90',  22222, 500)
insert into @t values (9, 'Иван',   'Иванов', 'м',  null,        11111, 600);




Я так понимаю, в моём случае, раз у меня уже есть таблица с моими значениями, мне этого делать не надо?
...
Рейтинг: 0 / 0
Объединение строк
    #40017537
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nevillested,

правильно понимаете, я просто привел пример тестовых данных как оно в принципе должно выглядеть, а вам уже нужно самому модифицировать запрос на использование не @t таблицы, а вашей реальной
...
Рейтинг: 0 / 0
Объединение строк
    #40017678
godsql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Nevillested,

вообще-то, ваша задача, судя по приведенному примеру, описанию и результату от 10 ноя 20, 17:59
достаточно просто раскладывается на :
1) простой select с группировкой phone и sum_amount, где phone и sum_amount "не равны null" (или "не пустые")
что- то типа
Код: sql
1.
2.
3.
select min(client_id), max(firstname), max(surname), max(sex), max(date_birthday), max( age) , max(city ), max(e-mail) , max(timezone),sum_amount , phone from Table
where sum_amount is not null and  phone  is not null   -- или что там еще означает, что поле пустое
group by sum_amount , phone 



2) плюс, используя union all, собираем все оставшиеся строки, которые не схлопнулись по sum_amount , phone обычным select -ом
Код: sql
1.
2.
3.
union all
select client_id , firstname , surname , sex , date_birthday , age , city   ,  e-mail   , timezone , sum_amount , phone from Table
where phone is  null or sum_amount  is null 
...
Рейтинг: 0 / 0
Объединение строк
    #40017829
Nevillested
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
felix_ff, понял-принял, попробую подкрутить под свою таблицу.
godsql, спасибо за идею, звучит вроде правильно и адекватно, но что-то смущает, не могу понять что (может простота варианта?)
...
Рейтинг: 0 / 0
26 сообщений из 26, показаны все 2 страниц
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Объединение строк
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]