За последние 24 часа нас посетили 17873 программиста и 1653 робота. Сейчас ищут 929 программистов ...

помогите создать запрос

Тема в разделе "MySQL", создана пользователем ser_ega, 28 июн 2010.

  1. ser_ega

    ser_ega Активный пользователь

    С нами с:
    13 ноя 2008
    Сообщения:
    56
    Симпатии:
    0
    Здравствуйте уважаемые!
    есть таблица

    ID | DATEADD | PLUS | MINUS |
    1 | 2010-06-08 | 12 | -2 |
    2 | 2010-05-08 | 0 | -6 |
    3 | 2010-04-08 | 4 | -12 |
    4 | 2010-06-08 | 8 | 0 |
    5 | 2010-04-08 | 2 | -5 |

    Нужно создать запрос в котором был бы массив вида

    month | PLUS | MINUS |
    июнь | 20 | -2 |
    май | 0 | -6 |
    апрель | 6 | -17 |

    Смысл в чем: получить одним запросом массив за последние три месяца в котором поля PLUS и MINUS будут просуммированы в своем месяце.

    Для одного месяца не проблема это сделать но как сделать для трех последних пока не додумался?
     
  2. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Вообще:
    [sql]select mounth, sum(plus), sum(minus) from table where mounth in (@mounth, @mounth-1, @mounth-2) group by mounth[/sql]
    где @mounth - номер текущего месяца полученный скриптом или вычисленный от NOW()
    Из DATEADD можно получить месяц, но боюсь group by откажется работать по части поля...
     
  3. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    И какая буква лишняя? n, да?)
     
  4. ser_ega

    ser_ega Активный пользователь

    С нами с:
    13 ноя 2008
    Сообщения:
    56
    Симпатии:
    0
    поправлюсь...

    Дано:
    ID | FIO| DATEADD | PLUS | MINUS |
    1 | Иванов | 2010-06-08 | 12 | -2 |
    2 | Петров | 2010-05-08 | 0 | -6 |
    3 | Сидоров | 2010-04-08 | 4 | -12 |
    4 | Сидоров | 2010-06-08 | 8 | 0 |
    5 | Иванов | 2010-04-08 | 2 | -5 |
    Получить:

    Июнь || май || апрель ||
    plus | minus || plus | minus || plus | minus ||
    Иванов 12 -2 0 0 2 -5
    Петров 0 0 0 -6 0 0
    Сидоров 8 0 0 0 4 -12

    Сорри за неточность! такое реально?
     
  5. ser_ega

    ser_ega Активный пользователь

    С нами с:
    13 ноя 2008
    Сообщения:
    56
    Симпатии:
    0
    Вот такой простой запрос я сообразил

    SELECT FAM, DATEADD, SUM(Minus), SUM(Minus) order by FAM

    Но как сделать чтобы для каждого SUM(Minus) было свое условие по дате? чтобы считалась сумма за разные промежутки времени?
     
  6. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    В лоб - для одного месяца:
    [sql]SELECT FAM, month(DATEADD), SUM(Minus), SUM(Minus) where month(DATEADD)=@month group by FAM [/sql]
    где month(@smth) - функция, вычисляющая месяц от даты.
    Далее через join или union можно объединить с остальными двумя месяцами.
     
  7. ser_ega

    ser_ega Активный пользователь

    С нами с:
    13 ноя 2008
    Сообщения:
    56
    Симпатии:
    0
    ну UNION не совсем то что мне надо
    http://www.mysql.ru/docs/man/UNION.html
    Он как бы добавляет один результат к другому.

    а join не могу понять как мне может помочь!

    Может более конкретный примерчик покажете?
     
  8. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    С Union там получится достаточно извращенно в логике обработки.
    Пока месяц не меняется считываем данные, как только месяц изменился считываем данные в переменные другого месяца. Плюс соответствие по фамилиям. Не сложно, но достаточно муторно и не сразу понятно при чтении кода.

    Если сделать join по фамилиям (а лучше по id людей), то получится требуемая таблица, только названия месяцев надо будет дополнительно обработать.
     
  9. ser_ega

    ser_ega Активный пользователь

    С нами с:
    13 ноя 2008
    Сообщения:
    56
    Симпатии:
    0
    Думал что заработало, но у всех пользователей получаются одинаковые значения :(((
    [sql]select
    personal.id_p,
    personal.fam_p, personal.name_p, personal.otch_p,
    otgul.dateadd_o,

    (SELECT SUM(Minus_o)
    FROM otgul
    WHERE (dateadd_o >'2010-07-01') and (dateadd_o <'2010-08-01')
    ) Minus_1,
    (SELECT SUM(Plus_o)
    FROM otgul
    WHERE (dateadd_o >'2010-07-01') and (dateadd_o <'2010-08-01')
    ) Plus_1,
    (SELECT SUM(Minus_o+Plus_o)
    FROM otgul
    WHERE (dateadd_o <'2010-08-01')
    ) SUM_1,

    (SELECT SUM(Minus_o)
    FROM otgul
    WHERE (dateadd_o >'2010-08-01') and (dateadd_o <'2010-09-01')
    ) Minus,
    (SELECT SUM(Plus_o)
    FROM otgul
    WHERE (dateadd_o >'2010-08-01') and (dateadd_o <'2010-09-01')
    ) Plus,
    (SELECT SUM(Minus_o+Plus_o)
    FROM otgul
    WHERE (dateadd_o <'2010-09-01')
    ) SUM
    FROM personal, otgul
    WHERE (personal.id_p=otgul.id_p_o) Group by id_p[/sql]

    Помогите это преобразовать в рабочий код с использование JOIN
     
  10. ser_ega

    ser_ega Активный пользователь

    С нами с:
    13 ноя 2008
    Сообщения:
    56
    Симпатии:
    0
    Ребят подскажите хотя бы структуру JOIN в моем случае, чето я не могу понять каким образом такой запрос сотворить... Натолкните на путь истинный!
     
  11. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    а я бы сделал сводную таблицу с просуммированными данными не заморачивался со всякими дикими запросами
     
  12. ser_ega

    ser_ega Активный пользователь

    С нами с:
    13 ноя 2008
    Сообщения:
    56
    Симпатии:
    0
    имеется ввиду массив данных? если это так, то прийдется же много циклов создавать с перебором данных, чтобы не попутать все...
    или я не правильно понял?
     
  13. ser_ega

    ser_ega Активный пользователь

    С нами с:
    13 ноя 2008
    Сообщения:
    56
    Симпатии:
    0
    Снова вернулся к этому вопросу. Может какие то свежие идеи есть?
    Сводная таблица хорошо конечно, но эти циклы в цикле....
     
  14. runner

    runner Активный пользователь

    С нами с:
    16 апр 2010
    Сообщения:
    343
    Симпатии:
    1
    Адрес:
    Ташкент
    [sql]
    select t.id_p_o,p.fam_p,p.name_p,p.otch_p,month(t.dateadd_o) month_o,sum(t.plus_o) plus_o,sum(t.minus_o) minus_o from otgul t left outer join personal p on t.id_p_o=p.id_p group by t.id_p_o,month(t.dateadd_o) order by t.id_p_o ASC,month(t.dateadd_o) DESC
    [/sql]
    недостатки
    1) если нет данных за определенный месяц, то запись отсутствует
    2) название месяца нужно вставлять вручную

    Если за последние 3 месяца то нужно добавить условие
    [sql]
    select t.id_p_o,p.fam_p,p.name_p,p.otch_p,month(t.dateadd_o) month_o,sum(t.plus_o) plus_o,sum(t.minus_o) minus_o from otgul t left outer join personal p on t.id_p_o=p.id_p WHERE t.dateadd_o > subdate( now( ) , INTERVAL 3 MONTH ) group by t.id_p_o,month(t.dateadd_o) order by t.id_p_o ASC,month(t.dateadd_o) DESC
    [/sql]

    Поскольку у тебя данные за 2010 год, то запрос ничего не вернет.
     
  15. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Что-то я не понял Вашу проблему...
    Простой запрос:
    select month(DATEADD) m, sum(plus), sum(minus) from table
    group by year(DATEADD) desc, m desc
    limit 3
    возвращает то, что Вам нужно.
     
  16. runner

    runner Активный пользователь

    С нами с:
    16 апр 2010
    Сообщения:
    343
    Симпатии:
    1
    Адрес:
    Ташкент
    твой запрос возвращает суммы по месяцам:

    m sum(plus) sum(minus)
    6 20 -2
    5 0 -6
    4 6 -17

    а нужно суммы по человеку+ месяцам

    Июнь || май || апрель ||
    plus | minus || plus | minus || plus | minus ||
    Иванов 12 -2 0 0 2 -5
    Петров 0 0 0 -6 0 0
    Сидоров 8 0 0 0 4 -12
     
  17. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Можно и для этого запрос сварганить и разными способами, например так:
    select t.fio
    , sum(if(EXTRACT(YEAR_MONTH FROM t.dateadd) = tm.ym,t.plus,0)) as p1
    , sum(if(EXTRACT(YEAR_MONTH FROM t.dateadd) = tm.ym,t.minus,0)) as m1
    , sum(if(EXTRACT(YEAR_MONTH FROM t.dateadd) = period_add(tm.ym,-1),t.plus,0)) as p2
    , sum(if(EXTRACT(YEAR_MONTH FROM t.dateadd) = period_add(tm.ym,-1),t.minus,0)) as m2
    , sum(if(EXTRACT(YEAR_MONTH FROM t.dateadd) = period_add(tm.ym,-2),t.plus,0)) as p3
    , sum(if(EXTRACT(YEAR_MONTH FROM t.dateadd) = period_add(tm.ym,-2),t.minus,0)) as m3
    from tt as t
    left join (select EXTRACT(YEAR_MONTH FROM dateadd) ym from tt order by dateadd desc limit 1) as tm on tm.ym
    group by t.fio