Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / распределение данных по месяцам / 18 сообщений из 18, страница 1 из 1
27.03.2016, 19:33
    #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
27.03.2016, 19:35
    #39201514
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
распределение данных по месяцам
Перейти из ворда в эксель и использовать cross tab.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
27.03.2016, 20:57
    #39201558
Serega325
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
распределение данных по месяцам
Dimitry SibiryakovПерейти из ворда в эксель и использовать cross tab.

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

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

CASE

Тут похоже проблема не в CASE, а в том как раскидать несколько строк для одного месяца в разные записи.
...
Рейтинг: 0 / 0
28.03.2016, 06:13
    #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
28.03.2016, 09:37
    #39201743
tip78
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
распределение данных по месяцам
...
Рейтинг: 0 / 0
28.03.2016, 09:40
    #39201752
tip78
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
распределение данных по месяцам
frakstip78,
если бы были не строки а числовые агрегаты - то можно было бы обойтись case или iif.
А так похоже что без процедуры не выйдет. или без промежуточной таблицы.

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

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

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

- Какая картинка с другого сайта??
- Кто сказал что в задаче присутствует ПХП?
- Какая статистика если в задаче тип данных - string?
- TINYINT - это вы про MySQL или про что? В Firebird нет такого типа данных.
- вопрос про m - это мне что-ли? Который m вас интересует?
- не затруднит ли вас привести свой элементарный пример решения исходной задачи?
...
Рейтинг: 0 / 0
28.03.2016, 14:26
    #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
28.03.2016, 14:33
    #39202139
tip78
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
распределение данных по месяцам
но это 1 вариант, есть и другой, нормальный, когда дата это DATA и можно через DATE_FORMAT() вытаскивать месяц
...
Рейтинг: 0 / 0
28.03.2016, 14:37
    #39202147
tip78
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
распределение данных по месяцам
*DAT E
...
Рейтинг: 0 / 0
28.03.2016, 15:06
    #39202190
miwaonline
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
распределение данных по месяцам
tip78,

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

И - да, это форум о файрберд. Привычки с мускля здесь не в кассу.
...
Рейтинг: 0 / 0
28.03.2016, 17:28
    #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
28.03.2016, 17:37
    #39202401
fraks
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
распределение данных по месяцам
Главный недостаток моего решения - наличие процедуры. На боевой базе обычно это недопустимое решение.
Наверняка можно от нее избавиться, но интерес уже пропал.
...
Рейтинг: 0 / 0
28.03.2016, 22:56
    #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
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / распределение данных по месяцам / 18 сообщений из 18, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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