За последние 24 часа нас посетили 16352 программиста и 1323 робота. Сейчас ищут 938 программистов ...

простенький SQL (учимся думать series)

Тема в разделе "Прочее", создана пользователем флоппик, 31 мар 2010.

  1. Есть табличка с платежами, поступающими в течении дня. Примерно такая (лишнее поскипано):
    [sql]CREATE TABLE `payments` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `account_id` varchar(20) NOT NULL,
    `amount` decimal(20,2) NOT NULL,
    `paydate` datetime NOT NULL);[/sql]
    требуется построить запросом отчет, выбирающий суммарный доход за каждый день за указанный произвольный период времени, без пропусков. Т.е. если в этот день не было платежей, то доход = 0, но строка в отчете есть.
    Типа так:
    Код (Text):
    1. Дата    Принятая сумма
    2. 2010-03-01  2950,00
    3. 2010-03-02  0,00
    4. 2010-03-03  2955,00
    5. 2010-03-04  5215,00
    6. 2010-03-05  0,00
    7. 2010-03-06  4180,00
    Желающие подумать... могут подумать. ;)
     
  2. engager

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

    С нами с:
    21 янв 2009
    Сообщения:
    1.106
    Симпатии:
    1
    В оракле это могло бы выглядеть так:

    [sql]SELECT
    ch.dt,
    pays.amount
    FROM
    (SELECT LEVEL + s_date dt FROM DUAL CONNECT BY LEVEL < (e_date - s_date)) ch,
    (select sum(amount) amount, TRUNC(paydate) paydate from payments group by TRUNC(paydate)) pays
    where
    pays.paydate (+)= ch.dt

    -- s_date, e_date - переменные типа DATE начало периода и конец [/sql]

    SELECT LEVEL + s_date FROM DUAL CONNECT BY LEVEL < (e_date - s_date) создает рекордсет с рядом дат из диапазона s_date .. e_date
    а дальше делаем левое связывание.
    в мускуле помнится тоже есть таблица dual, но не уверен, пройдет ли такой фокус.
    если рассматривать в разрезе абстрактной базы, то, опять же если база позволяет использовать временные таблицы, можно эту самую таблицу создать, напихать туда значений дат в цикле и опять лефт джоин
     
  3. engager, я знаю, как это делается в оракле :)
    Суть как раз в том, что надо было в мускуле ) Хотя тут для мускула видно половинку решения )
     
  4. engager

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

    С нами с:
    21 янв 2009
    Сообщения:
    1.106
    Симпатии:
    1
    флоппик
    ну вдруг кому полезно будет :)
     
  5. Simpliest

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

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Фокус пройдет, но без подвыподверта не получится сгенерировать последовательность дат.
     
  6. Ну, да. engager прав, на самом деле.
    [sql]DELIMITER $$

    CREATE DEFINER=`root`@`%` PROCEDURE `calendar`( pstart date, pstop date)
    DETERMINISTIC
    BEGIN
    DECLARE thisdate date;
    DROP TABLE IF EXISTS tmp_calendar;
    CREATE TABLE tmp_calendar( dt date );
    SET thisdate=pstart;
    INSERT INTO tmp_calendar VALUES(pstart);
    WHILE thisdate < pstop DO
    SET thisdate = adddate( thisdate, INTERVAL 1 DAY );
    INSERT INTO tmp_calendar VALUES( thisdate );
    END WHILE;
    END$$[/sql]

    Вдруг кому пригодится? Табличку скорее всего лучше использовать временную, но в реальной задачке она еще нужна некоторое время, поэтому живет.

    А у меня продолжение веселья. :) в этой табличке на самом деле, есть еще поле "dealer_id" ... и мне нужно построить отчет по дилерам развернутый в ширину. =) Пойду дальше тренировать свои тайные знания мускула )
     
  7. Simpliest

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

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    флоппик
    вариант с хранимкой я знаю, мне интереснее получить это чистыми запросами :)
     
  8. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    С помощью циклов сделать подневку и по ней выбирать?
    Т.е. что-то типа
    FOR bla-bla d++ bla-bla IF (SELECT money FROM bla WHERE bla=d (или в DATETIME из таймштампа) as bla, bla, 0)
     
  9. akrinel

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

    С нами с:
    26 янв 2009
    Сообщения:
    955
    Симпатии:
    1
    Адрес:
    Spb
    Я немного не в тему, но все же:

    А не быстрее будет выборка стандартная по существующим датам, которую потом "размочить" нулевыми датами на любом скриптовом языке?
     
  10. Будет. Но в моем случае есть универсальный софт, который формирует отчет из полученного результсета, т.е. в системе хранятся только запросы, а отчет генерится единообразно