powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / распределение данных по месяцам
18 сообщений из 18, страница 1 из 1
распределение данных по месяцам
    #39201513
Serega325
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте,
есть таблица в firebird

данные| дата
string1 |01.01.2015
string2 | 04.03.2015
string3 | 17.06.2015
string4 | 09.03.2015
string5 | 25.04.2015
string6 | 25.03.2015

Данные выводятся в word таблицу

Как получить на выходе

Январь Февраль Март Апрель Май Июнь Июль Август Сентябрь Октябрь Декабрь
string1 string2 string5 string3
string4
string6
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39201514
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Перейти из ворда в эксель и использовать cross tab.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39201558
Serega325
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovПерейти из ворда в эксель и использовать cross tab.

Мне нужно sql запросом распределить данные по месяцам
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39201567
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Serega325,

CASE
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39201618
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну создайте колонку `my` и кидайте туда 215,315,415
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39201650
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tip78,
если бы были не строки а числовые агрегаты - то можно было бы обойтись case или iif.
А так похоже что без процедуры не выйдет. или без промежуточной таблицы.
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39201651
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисSerega325,

CASE

Тут похоже проблема не в CASE, а в том как раскидать несколько строк для одного месяца в разные записи.
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39201655
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вобщем примерно так вышло, вероятно можно упростить или обойтись без СП.
Это чисто как демонстрация идеи.

Таблица и данные:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
create table test(
  id integer not null primary key,
  data date,
  str varchar(10)
);

insert into test(id, data, str) values(1, '01.01.2015', 'string 1');
insert into test(id, data, str) values(2, '04.03.2015', 'string 2');
insert into test(id, data, str) values(3, '17.06.2015', 'string 3');
insert into test(id, data, str) values(4, '09.03.2015', 'string 4');
insert into test(id, data, str) values(5, '25.04.2015', 'string 5');
insert into test(id, data, str) values(6, '25.03.2015', 'string 6');



Промежуточная процедура, в ней добавляем номер месяца и номер строки в месяце.
Код: plsql
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.
create procedure test1
returns (
  data date,
  str  varchar(10),
  m    integer,
  r    integer
)
as
declare variable mc integer;
begin

  mc = 0; -- "текущий" месяц

  for select
   test.data,
   test.str,
   extract(month from data) as m
  from test
  order by 3
  into :data, :str, :m
  do begin
     if (:m <> :mc) then begin
       mc = m;
       r = 1;
     end else begin
       r = r + 1;
     end
     suspend;
     end
end




Ну и собственно вот так получаем данные:
Код: plsql
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.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
execute block
returns (
  r   integer,  -- номер строки
  m01 varchar(10),
  m02 varchar(10),
  m03 varchar(10),
  m04 varchar(10),
  m05 varchar(10),
  m06 varchar(10),
  m07 varchar(10),
  m08 varchar(10),
  m09 varchar(10),
  m10 varchar(10),
  m11 varchar(10),
  m12 varchar(10)
)
as
declare variable vr integer;
declare variable vm integer;
declare variable vstr varchar(10);
begin
  r = 0; -- начальная строка

  for select
    r, m, str
  from test1
  order by r, m
  into :vr, :vm, :vstr
  do begin
     -- если в данных пошла новая строка - заведем новую запись и зачистим поля данных
     if (:vr > :r) then begin
       if (:r > 0) then suspend; -- вытолкнем предыдущую строку если она была
       r = vr;
       m01 = '';
       m02 = '';
       m03 = '';
       m04 = '';
       m05 = '';
       m06 = '';
       m07 = '';
       m08 = '';
       m09 = '';
       m10 = '';
       m11 = '';
       m12 = '';
     end
     -- раскидаем значения по полям месяцев
     if (:vm =  1) then m01 = vstr;
     if (:vm =  2) then m02 = vstr;
     if (:vm =  3) then m03 = vstr;
     if (:vm =  4) then m04 = vstr;
     if (:vm =  5) then m05 = vstr;
     if (:vm =  6) then m06 = vstr;
     if (:vm =  7) then m07 = vstr;
     if (:vm =  8) then m08 = vstr;
     if (:vm =  9) then m09 = vstr;
     if (:vm = 10) then m10 = vstr;
     if (:vm = 11) then m11 = vstr;
     if (:vm = 12) then m12 = vstr;
     end -- for select
  if (:r > 0) then suspend; -- вытолкнем последнюю строку если вообще были данные
end




Результат, как и требовалось:


R M01_____ M02_____ M03_____ M04_____ M05_____ M06_____ M07_____ M08_____ M09_____ M10_____ M11_____ M12_____1 string 1 string 2 string 5 string 3 2 string 4 3 string 6
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39201743
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39201752
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
frakstip78,
если бы были не строки а числовые агрегаты - то можно было бы обойтись case или iif.
А так похоже что без процедуры не выйдет. или без промежуточной таблицы.

да это обычная статистика по месяцам, какие нафиг case
её вообще можно было сделать внутри пхп
да и внутри SQL делается элементарно
а тут грабля на грабле, нафига спрашивается понадобилась вам 'm' вообще? сделали зачем-то вместо лёгкого TINYINT - VARCHAR
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39202072
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tip78frakstip78,
если бы были не строки а числовые агрегаты - то можно было бы обойтись case или iif.
А так похоже что без процедуры не выйдет. или без промежуточной таблицы.

да это обычная статистика по месяцам, какие нафиг case
её вообще можно было сделать внутри пхп
да и внутри SQL делается элементарно
а тут грабля на грабле, нафига спрашивается понадобилась вам 'm' вообще? сделали зачем-то вместо лёгкого TINYINT - VARCHAR

Такое ощущение что вы отвечаете на вопросы из какой-то другой ветки.

- Какая картинка с другого сайта??
- Кто сказал что в задаче присутствует ПХП?
- Какая статистика если в задаче тип данных - string?
- TINYINT - это вы про MySQL или про что? В Firebird нет такого типа данных.
- вопрос про m - это мне что-ли? Который m вас интересует?
- не затруднит ли вас привести свой элементарный пример решения исходной задачи?
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39202119
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я уже написал решение
вот его таблица
Serega325данные| дата
string1 |01.01.2015
string2 | 04.03.2015
string3 | 17.06.2015
string4 | 09.03.2015
string5 | 25.04.2015
string6 | 25.03.2015


и ему надо вывести их в word-таблицу в таком виде:
Код: plsql
1.
2.
3.
4.
Январь Февраль Март     Апрель  Май  Июнь   Июль Август  Сентябрь Октябрь   Декабрь
string1              string2   string5         string3
                       string4 
                       string6


суть одна, что ПХП, что word - форматированием заниматься будут они, главное данные достать
ну так вот добавляется колонка `my` (MonthYear):
115
315
615
315
415
315

(это если по годам всё-таки надо разделять, а то можно и выкинуть 15)
а потом GROUP BY `my` и всё

а вы там нагородили какие-то процедуры, функции, циклы
жесть (

хайлодеры рекомендуют: в sql всё должно быть просто, без сложных запросов. Сложные запросы надо разбивать на простые. Городить лишнего не надо. БД - самое узкое место ВСЕГДА, помните об этом.
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39202139
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
но это 1 вариант, есть и другой, нормальный, когда дата это DATA и можно через DATE_FORMAT() вытаскивать месяц
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39202147
tip78
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
*DAT E
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39202190
miwaonline
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tip78,

Осталось только придумать, как group by сделает кросс-таб. Хотя, после фразы «БД - самое узкое место ВСЕГДА»© я не уверен, что можно еще что-то придумать.

И - да, это форум о файрберд. Привычки с мускля здесь не в кассу.
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39202393
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tip78 я уже написал решение


Это не решение, это просто направление в котором как вам кажется находится решение. Но вам кажется неверно.
Подтверждением правоты может быть рабочий запрос на SQL.

tip78суть одна, что ПХП, что word - форматированием заниматься будут они,

Я не знаю какой смысл вы вкладываете в слово "форматирование".
В рассматриваемом случае Данные - это строки. Там нечего форматировать.
Исходная задача состоит в том что бы достать запросом прямоугольную таблицу данных, уже развернутую по полям месяцев.

Сам я таким не увлекаюсь, для такой цели у меня в клиенте написана своя прокладка которая по данным из процедуры аналогичной TEST1 автоматом разворачивает колонки в ширину в моем "датасете". Однако бывают такие условия когда клиента просто нет (например это IBExpert или isql или просто окошко в программе для выполнения непредусмотренных запросов), и выполнить задачу чисто средствами SQL - это бывает удобно.

tip78главное данные достать
ну так вот добавляется колонка `my` (MonthYear):
115
315
615
315
415
315

(это если по годам всё-таки надо разделять, а то можно и выкинуть 15)
а потом GROUP BY `my` и всё


колонку, т.е. поле в таблицу можно не добавлять ибо оно элементарно вычисляется из даты встроенной в Firebird функцией, и в моем коде эта функция приведена и достает как раз месяц. Можно обойтись и кастом, и подстрокой... масса вариантов.
И сгруппировать по этому вычисленному полю можно, если бы это было нужно.

GROUP BY подразумевает что какие-то поля обрабатываются агрегатной функцией. Вам видимо кажется что сделать SUM() по строковому полю - это хорошая идея. Но смысла в ней - ноль.

tip78хайлодеры рекомендуют: в sql всё должно быть просто, без сложных запросов. Сложные запросы надо разбивать на простые. Городить лишнего не надо. БД - самое узкое место ВСЕГДА, помните об этом.

Просто написать на SQL - это не просто :)
Уровень допустимой сложности у каждого свой.
На мой взгляд мое решение не относится к сложным, оно вполне доступно для понимания, отладки и сопровождения.
И скорее всего его можно улучшить и написать более изящно.

Как хайлодеру скажу, что в жизни есть БД и в иных местах чем на хостинге под MySQL и PHP.
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39202401
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Главный недостаток моего решения - наличие процедуры. На боевой базе обычно это недопустимое решение.
Наверняка можно от нее избавиться, но интерес уже пропал.
...
Рейтинг: 0 / 0
распределение данных по месяцам
    #39202607
Serega325
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fraksВобщем примерно так вышло, вероятно можно упростить или обойтись без СП.
Это чисто как демонстрация идеи.

Таблица и данные:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
create table test(
  id integer not null primary key,
  data date,
  str varchar(10)
);

insert into test(id, data, str) values(1, '01.01.2015', 'string 1');
insert into test(id, data, str) values(2, '04.03.2015', 'string 2');
insert into test(id, data, str) values(3, '17.06.2015', 'string 3');
insert into test(id, data, str) values(4, '09.03.2015', 'string 4');
insert into test(id, data, str) values(5, '25.04.2015', 'string 5');
insert into test(id, data, str) values(6, '25.03.2015', 'string 6');



Промежуточная процедура, в ней добавляем номер месяца и номер строки в месяце.
Код: plsql
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.
create procedure test1
returns (
  data date,
  str  varchar(10),
  m    integer,
  r    integer
)
as
declare variable mc integer;
begin

  mc = 0; -- "текущий" месяц

  for select
   test.data,
   test.str,
   extract(month from data) as m
  from test
  order by 3
  into :data, :str, :m
  do begin
     if (:m <> :mc) then begin
       mc = m;
       r = 1;
     end else begin
       r = r + 1;
     end
     suspend;
     end
end




Ну и собственно вот так получаем данные:
Код: plsql
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.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
execute block
returns (
  r   integer,  -- номер строки
  m01 varchar(10),
  m02 varchar(10),
  m03 varchar(10),
  m04 varchar(10),
  m05 varchar(10),
  m06 varchar(10),
  m07 varchar(10),
  m08 varchar(10),
  m09 varchar(10),
  m10 varchar(10),
  m11 varchar(10),
  m12 varchar(10)
)
as
declare variable vr integer;
declare variable vm integer;
declare variable vstr varchar(10);
begin
  r = 0; -- начальная строка

  for select
    r, m, str
  from test1
  order by r, m
  into :vr, :vm, :vstr
  do begin
     -- если в данных пошла новая строка - заведем новую запись и зачистим поля данных
     if (:vr > :r) then begin
       if (:r > 0) then suspend; -- вытолкнем предыдущую строку если она была
       r = vr;
       m01 = '';
       m02 = '';
       m03 = '';
       m04 = '';
       m05 = '';
       m06 = '';
       m07 = '';
       m08 = '';
       m09 = '';
       m10 = '';
       m11 = '';
       m12 = '';
     end
     -- раскидаем значения по полям месяцев
     if (:vm =  1) then m01 = vstr;
     if (:vm =  2) then m02 = vstr;
     if (:vm =  3) then m03 = vstr;
     if (:vm =  4) then m04 = vstr;
     if (:vm =  5) then m05 = vstr;
     if (:vm =  6) then m06 = vstr;
     if (:vm =  7) then m07 = vstr;
     if (:vm =  8) then m08 = vstr;
     if (:vm =  9) then m09 = vstr;
     if (:vm = 10) then m10 = vstr;
     if (:vm = 11) then m11 = vstr;
     if (:vm = 12) then m12 = vstr;
     end -- for select
  if (:r > 0) then suspend; -- вытолкнем последнюю строку если вообще были данные
end




Результат, как и требовалось:


R M01_____ M02_____ M03_____ M04_____ M05_____ M06_____ M07_____ M08_____ M09_____ M10_____ M11_____ M12_____1 string 1 string 2 string 5 string 3 2 string 4 3 string 6



Спасибо огромное.
...
Рейтинг: 0 / 0
18 сообщений из 18, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / распределение данных по месяцам
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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