Есть ли более простой способ сделать этот запрос? - PullRequest
1 голос
/ 30 апреля 2019

У меня есть две разные таблицы из базы данных с именами "empleados" и "fichajes".У empleados есть данные о сотрудниках, а у фишхейса есть дата и время, когда они начали работать.

Я хочу получить общее время работы, выполненное конкретным сотрудником между двумя датами, скажем, с 20-го по 29-е.

У меня есть этот запрос, который я использую с Dapper на C #:

SELECT CONCAT(e.nombre, " " ,e.apellido) as fullName, tfichajes.total 
FROM empleados e 
    INNER JOIN (
                SELECT f1.nif, 
                    SEC_TO_TIME(SUM(TIME_TO_SEC(f1.fechasalida) - TIME_TO_SEC(f1.fechaentrada))) AS total 
                    FROM fichajes f1 
                    WHERE f1.fechasalida <= '2019-04-29' 
                    and f1.fechaentrada >= '2019-04-20' 
                    GROUP BY f1.nif
                ) AS tfichajes 
        ON e.nif = tfichajes.nif 
WHERE e.nif = '33333333P'

Это прекрасно работает, но мне было интересно, возможно ли сделать его проще.

Этоэто код, который у меня есть в моей программе:

public static List<string> CalculaTotalHoras(string nif, DateTime fechaEntrada, DateTime fechaSalida)
{
    var dbCon = DBConnection.Instancia();
    if (dbCon.Conectado())
    {
        string format = "yyyy-MM-dd";
        List<string> result = new List<string>();
        using (IDbConnection conexion = dbCon.Conexion)
        {
            var output = conexion.Query($"SELECT CONCAT(e.nombre, \" \" ,e.apellido) as fullName, tfichajes.total " +
                $"FROM empleados e INNER JOIN (SELECT f1.nif, SEC_TO_TIME(SUM(TIME_TO_SEC(f1.fechasalida) - TIME_TO_SEC(f1.fechaentrada))) AS total " +
                $"FROM fichajes f1 where f1.fechasalida <= '{fechaSalida.ToString(format)}' and f1.fechaentrada >= '{fechaEntrada.ToString(format)}' GROUP BY f1.nif) " +
                $"as tfichajes ON e.nif = tfichajes.nif where e.nif = '{ nif }';").ToList();

            var i = 0;
            foreach (IDictionary<string, object> row in output)
            {
                foreach (var pair in row)
                {
                    if (i == 0)
                    {
                        result.Add(pair.Value.ToString());
                        i++;
                    }
                    else
                    {
                        result.Add(pair.Value.ToString());
                    }
                }
            }
            return result;
        }
    }
    else return null;
}

Если у вас есть проблемы с читабельностью кода здесь у вас есть gyazo. Рабочее время fichajes таблица и сотрудники empleados таблица.

При таком точном запросе ожидаемые результаты составляют Alvaro Arguelles 00:05:00, и в коде я хочучтобы разделить Alvaro Arguelles и 00:05:00 в списке result.

Я сделал это намного сложнее, чем на самом деле?

1 Ответ

1 голос
/ 30 апреля 2019

Ваш запрос может быть значительно упрощен.Ваш внутренний запрос выбирает ВСЕХ сотрудников, работающих на указанную дату, я бы начал с запроса INNER в качестве основной таблицы FROM, получая данные для одного сотрудника.Затем присоединитесь к сотруднику, чтобы получить имя.

select
      CONCAT(e.nombre, " " ,e.apellido) as fullName,
      OneEmp.Total
   from
      ( select
              f1.nif,
              SEC_TO_TIME( SUM(TIME_TO_SEC(f1.fechasalida) 
                             - TIME_TO_SEC(f1.fechaentrada))) AS total 
           from
              fichajes f1
           where
                  f1.nif = '33333333P'
              AND f1.fechasalida >= '2019-04-20' 
              AND f1.fechasalida <= '2019-04-29' ) OneEmp
         JOIN empleados e
            on OneEmp.nif = e.nif

Поскольку ваш запрос суммируется на одного сотрудника, он все равно возвращает только одну строку.Таким образом, приведенный выше запрос вернет 1 строку, 2 столбца ... имя и итог.Должны быть в состоянии прочитать эти два значения напрямую.

Но, как прокомментировали другие, ПАРАМЕТРИРОВАТЬ вызовы вашего запроса.

...