За последние 24 часа нас посетили 18099 программистов и 1603 робота. Сейчас ищут 1723 программиста ...

Помогите с запросом

Тема в разделе "MySQL", создана пользователем Alex_1984, 24 фев 2016.

  1. Alex_1984

    Alex_1984 Новичок

    С нами с:
    10 дек 2014
    Сообщения:
    133
    Симпатии:
    0
    таблица
    id | employeeid | workdate | hourscount

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

    Код (PHP):
    1. select  Distinct employeeid, name, 
    2. (select sum(hourscount) from timesheet where workdate between '2016-02-01' and '2016-02-15') as firstsum,  
    3. (select sum(hourscount) from timesheet where workdate between '2016-02-16' and '2016-02-29') as secondsum from timesheet 
    4. join employees on timesheet.employeeid = employees.id
    считает естественно не правильно.

    Добавлено спустя 30 минут 41 секунду:
    правильно вроде считает
    Код (PHP):
    1. select  Distinct employeeid, name, 
    2.  
    3. (select sum(hourscount) from timesheet 
    4. where workdate between date('2016-02-01') and date('2016-02-15') and timesheet.employeeid = employees.id) as firstsum,  
    5.  
    6. (select sum(hourscount) from timesheet 
    7. where workdate between date('2016-02-16') and date('2016-02-29') and timesheet.employeeid = employees.id) as secondsum from timesheet 
    8.  
    9. join employees on timesheet.employeeid = employees.id
     
  2. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.115
    Симпатии:
    1.244
    Адрес:
    там-сям
    для каждого работника: GROUP BY employeeid
    посчитать сумму отработанных часов: SUM(hourscount)
    за определенный промежуток времени: WHERE workdate BETWEEN '2016-02-01' AND '2016-02-15'

    Клеим всё вместе по правилам:
    Код (PHP):
    1. SELECT `employeeid`, SUM(`hourscount`) AS `total`
    2. FROM `timesheet`
    3. WHERE `workdate` BETWEEN '2016-02-01' AND '2016-02-15'
    4. GROUP BY `employeeid` 
    Добавлено спустя 3 минуты 9 секунд:
    Если хочется добавить что-то из таблицы "работники", можно этот запрос использовать в качестве под-запроса:
    Код (PHP):
    1. SELECT e.`name`, s.*
    2. FROM 
    3.   `employees` AS e LEFT JOIN
    4.   ( 
    5.     SELECT `employeeid`, SUM(`hourscount`) AS `total`
    6.     FROM `timesheet`
    7.     WHERE `workdate` BETWEEN '2016-02-01' AND '2016-02-15'
    8.     GROUP BY `employeeid` 
    9.   ) AS s ON e.`id` = s.`employeeid`
    Добавлено спустя 1 минуту 31 секунду:
    LEFT JOIN даёт нам возможность вывести всех работников, даже если в указанный период у кого-то из них нет отработанных часов. Будут просто пустые места вместо цифр.

    Добавлено спустя 4 минуты 46 секунд:
    Если нужны два рабочих периода, то сделай по образцу два LEFT JOINа с подзапросами.

    [оффтопик] DISTINCT обычно служит признаком неуверенности автора ))) если не понимаешь, что происходит, не используй его. лучше не прятать от себя логические ошибки. [/оффтопик]
     
  3. Alex_1984

    Alex_1984 Новичок

    С нами с:
    10 дек 2014
    Сообщения:
    133
    Симпатии:
    0
    Спасибо за разъяснение, буду разбираться. join не очень понимаю
     
  4. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.115
    Симпатии:
    1.244
    Адрес:
    там-сям
  5. Alex_1984

    Alex_1984 Новичок

    С нами с:
    10 дек 2014
    Сообщения:
    133
    Симпатии:
    0
    спс, только вчера это смотрел, тут проблема не в том что я гуглить не умею, а в том что вот не понимаю я его нихрена и все тут))

    вот как это работает
    Код (PHP):
    1. select  employeeid, name, 
    2. (select sum(hourscount) from timesheet 
    3. where workdate between date('2016-02-01') and date('2016-02-15') and timesheet.employeeid = employees.id) as firstsum,  
    4. (select sum(hourscount) from timesheet 
    5. where workdate between date('2016-02-16') and date('2016-02-29') and timesheet.employeeid = employees.id) as secondsum from timesheet 
    6. join employees on timesheet.employeeid = employees.id group by employees.id
    я понимаю, а куда в твоем примере второй left join вставить, нет
     
  6. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.115
    Симпатии:
    1.244
    Адрес:
    там-сям
    Ты видишь как я оформил запрос регистром, обратными кавычками и отступами? Согласись так намного лучше читается. В твой запрос мне смотреть страшно.
    А дополнительные джойны пишутся очень просто: последовательно друг за другом: FROM a JOIN b ON b.x=a.x JOIN c ON c.z=a.z … и т.д.

    Добавлено спустя 2 минуты 45 секунд:
    Вместо любой таблицы ты можешь вставить подзапрос в круглых скобочках и дать ему "имя".
    (…) AS b
     
  7. Alex_1984

    Alex_1984 Новичок

    С нами с:
    10 дек 2014
    Сообщения:
    133
    Симпатии:
    0
    так понятней стало, осталось из этого запроса убрать пользователей которых нет в timesheet
     
  8. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.115
    Симпатии:
    1.244
    Адрес:
    там-сям
    Просто замени LEFT JOIN на JOIN и получишь желаемое.

    Т.е. нет в таймшит в выбранный период. Если задаться целью показать статистику за период, но при этом засветить всех, кто хоть раз попадался в таймшит, то запрос будет другой.
     
  9. Alex_1984

    Alex_1984 Новичок

    С нами с:
    10 дек 2014
    Сообщения:
    133
    Симпатии:
    0
    Код (PHP):
    1. SELECT e.name, s.*, s1.*
    2. FROM 
    3.   `employees` AS e 
    4.   
    5.   JOIN( 
    6.     SELECT `employeeid` as id, SUM(`hourscount`) AS `total`
    7.     FROM `timesheet`
    8.     WHERE `workdate` BETWEEN '2016-02-01' AND '2016-02-15' 
    9.     GROUP BY `employeeid` 
    10.   ) as s ON e.`id` = s.`id` 
    11.   
    12.   JOIN( 
    13.     SELECT `employeeid` as id1, SUM(`hourscount`) AS `total1`
    14.     FROM `timesheet`
    15.     WHERE `workdate` BETWEEN '2016-02-16' AND '2016-02-30' 
    16.     GROUP BY `employeeid` 
    17.   ) as s1 ON e.`id` = s1.`id1`

    так? одного пользователя выводит и считает не правильно
     
  10. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.115
    Симпатии:
    1.244
    Адрес:
    там-сям
    Выглядит правдоподобно. Думаю если и есть что-то неправильное, то это данные в таблице. Проверь их.
    Чего-нибудь задублировал или в дате ошибся.
     
  11. Alex_1984

    Alex_1984 Новичок

    С нами с:
    10 дек 2014
    Сообщения:
    133
    Симпатии:
    0
    получается что он правильно работает, показывает пользователей у которых total и total1 не = null, а нужно тех у которых total или total1 не = null
     
  12. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.984
    Симпатии:
    759
    Если есть вариант разделить таблицу на две, то ИМХО задача упростится в разы...
     
  13. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Херня какая-то, а не запрос. Нафига их два-то да ещё и с джоинами. Бред какой-то. Хочешь сумму за период - просто возьми ее.