{"id":665,"date":"2014-08-08T13:17:36","date_gmt":"2014-08-08T18:17:36","guid":{"rendered":"http:\/\/www.latindevelopers.com\/ivancp\/?p=665"},"modified":"2014-08-08T13:17:36","modified_gmt":"2014-08-08T18:17:36","slug":"consultas-de-referencias-cruzadas-en-mysql","status":"publish","type":"post","link":"https:\/\/www.latindevelopers.com\/ivancp\/2014\/08\/consultas-de-referencias-cruzadas-en-mysql\/","title":{"rendered":"Consultas de referencias cruzadas en MySQL"},"content":{"rendered":"<p>Hace alg\u00fan tiempo que uso Redmine para gestionar proyectos, la herramienta en general es buena pero a veces necesitaba de reportes diarios de tiempo utilizado por los miembros del proyecto.<\/p>\n<p>En este punto se me ocurri\u00f3 si podr\u00eda lograr una consulta de referencias cruzadas (al estilo MS Excel), MySQL no soporta consultas de ese tipo pero pueden simularse:<\/p>\n<p>1. Escribir la consulta principal que contenga las filas m\u00e1s importantes: project identifier, task subject y total_hours, todo en un rango de fechas.<\/p>\n<pre lang=\"sql\">select p.identifier, \r\n\te.issue_id, i.subject, round(sum(e.hours),2) as total_hours\r\n\tfrom redmine_nsp.time_entries e\r\n\tinner join redmine_nsp.issues i on e.issue_id = i.id\r\n\tinner join redmine_nsp.projects p on e.project_id = p.id\r\n\twhere e.spent_on between '2014-07-01' and '2014-07-07'\r\n group by p.identifier,e.issue_id;<\/pre>\n<p>Resultado:<\/p>\n<pre lang=\"text\">\r\n+------------+----------+----------------------------+-------------+\r\n| identifier | issue_id | subject                    | total_hours |\r\n+------------+----------+----------------------------+-------------+\r\n| bg02       |     3223 | Gestion de proyecto        |        0.25 |\r\n| bg04       |     3256 | 1.1 Preparaci\u00f3n del entor  |        0.63 |\r\n| emision    |     3251 | Desarrollar la aplicaci\u00f3n  |        3.97 |\r\n| nsp00      |     3236 | Preparar propuesta para G  |        2.02 |\r\n| nsp02      |     3234 | Subida al servidor de pro  |        0.52 |\r\n| nsp02      |     3240 | Agregar funcionalidad de   |        0.55 |\r\n| nsp02      |     3241 | Revertir el Documento      |        2.80 |\r\n| nsp02      |     3242 | Agregar Filtros en las vi  |        0.72 |\r\n| nsp02      |     3243 | Reportes de Cargo de entr  |        2.35 |\r\n| nsp02      |     3254 | Control de sesiones        |        3.23 |\r\n| nsp05      |     3252 | Mantenimiento del servido  |        0.18 |\r\n| nsp05      |     3253 | Mantenimiento a redmine    |        0.53 |\r\n| nsp06      |     3203 | Elaborar el visualzador d  |        0.23 |\r\n| nsp06      |     3228 | Evitar que se tome mas de  |        0.25 |\r\n| nsp06      |     3255 | Actualizar el porcentaje   |        1.50 |\r\n| nsp08      |     3239 | Asistencia remota          |        1.38 |\r\n+------------+----------+----------------------------+-------------+\r\n<\/pre>\n<p>2. Ahora queda averiguar quienes han estado activos en ese mismo rango de tiempo:<\/p>\n<pre lang=\"sql\">select e.user_id, u.login\r\nfrom redmine_nsp.time_entries e\r\n\tinner join redmine_nsp.users u on e.user_id = u.id \r\nwhere e.spent_on between '2014-07-01' and '2014-07-07'\r\ngroup by e.user_id;<\/pre>\n<pre lang=\"text\">+---------+----------+\r\n| user_id | login    |\r\n+---------+----------+\r\n|       1 | user1    |\r\n|       4 | user2    |\r\n|       5 | user3    |\r\n|       6 | user4    |\r\n+---------+----------+\r\n<\/pre>\n<p>3. La tarea es insertar ese resultado como columnas del primer resultado, de tal modo que tengamos una consulta de referencias cruzadas. He creado un procedimiento (no explico mucho al respecto) que hace esa tarea recibiendo como par\u00e1metros las fechas:<\/p>\n<pre lang=\"text\">\r\nDELIMITER $$\r\n\r\nCREATE PROCEDURE `get_range_summary`(dDate1 date,dDate2 date)\r\nBEGIN\r\n\r\nDECLARE done INT DEFAULT 0;\r\ndeclare p_user_id int;\r\ndeclare p_sql text;\r\ndeclare p_login varchar(255);\r\ndeclare c_users cursor for\r\n\tselect e.user_id, u.login\r\n\tfrom redmine_nsp.time_entries e\r\n\t\tinner join redmine_nsp.users u on e.user_id = u.id \r\n\twhere e.spent_on between  dDate1 and dDate2 \r\n\tgroup by e.user_id;\r\nDECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;\r\n\r\nset p_sql = 'select s.codigo,s.issue_id,s.subject ';\r\nopen c_users;\r\n\r\nread_loop: LOOP\r\n\tFETCH c_users INTO p_user_id, p_login;\r\n    IF done THEN\r\n      LEAVE read_loop;\r\n    END IF;\r\n\tset p_sql = concat(p_sql,\r\n      ', (select round(sum(t.hours),2) as total\r\n\t\tfrom redmine_nsp.time_entries t\r\n\t\twhere t.spent_on between \\'',dDate1,'\\' and \\'',dDate2,'\\'  \r\n        and t.issue_id = s.issue_id\r\n\t\tand t.user_id = ',p_user_id,') as `',p_login,'` ');\r\n\r\nEND LOOP;\r\n\r\nset @sql = concat(p_sql,' ,s.total_hours from \r\n\t(select p.identifier, e.issue_id, i.subject, \r\n         round(sum(e.hours),2) as total_hours\r\n\tfrom redmine_nsp.time_entries e\r\n\tinner join redmine_nsp.issues i on e.issue_id = i.id\r\n\tinner join redmine_nsp.projects p on e.project_id = p.id\r\n\twhere e.spent_on between \\'',dDate1,'\\' and \\'',dDate2,'\\' group by p.identifier,e.issue_id) as s');\r\n\r\n\r\nclose c_users;\r\n\r\nPREPARE stmt1 FROM @sql;\r\nEXECUTE stmt1;\r\nDEALLOCATE PREPARE stmt1; \r\n\r\nEND\r\n<\/pre>\n<p>Al probar con la llamada: <strong>call get_range_summary(&#8216;2014-07-01&#8242;,&#8217;2014-07-07&#8217;)<\/strong>:<\/p>\n<pre lang=\"text\">\r\n+---------+----------+----------------------------+-------+--------+---------+----------+-------------+\r\n| identif | issue_id | subject                    | user1 | user2  |  user3  |   user4  | total_hours |\r\n+---------+----------+----------------------------+-------+--------+---------+----------+-------------+\r\n| bg02    |       23 | Gestion de proyecto        |  NULL |   0.25 |    NULL |     NULL |        0.25 |\r\n| bg04    |       56 | 1.1 Preparaci\u00f3n del entor  |  NULL |   0.63 |    NULL |     NULL |        0.63 |\r\n| emision |       51 | Desarrollar la aplicaci\u00f3n  |  NULL |   NULL |    3.97 |     NULL |        3.97 |\r\n| nsp00   |       36 | Preparar propuesta para G  |  NULL |   2.02 |    NULL |     NULL |        2.02 |\r\n| nsp02   |       34 | Subida al servidor de pro  |  NULL |   0.52 |    NULL |     NULL |        0.52 |\r\n| nsp02   |       40 | Agregar funcionalidad de   |  NULL |   NULL |    0.55 |     NULL |        0.55 |\r\n| nsp02   |       41 | Revertir el Documento      |  1.40 |   NULL |    1.40 |     NULL |        2.80 |\r\n| nsp02   |       42 | Agregar Filtros en las vi  |  NULL |   NULL |    0.72 |     NULL |        0.72 |\r\n| nsp02   |       43 | Reportes de Cargo de entr  |  NULL |   NULL |    NULL |     2.35 |        2.35 |\r\n| nsp02   |       54 | Control de sesiones        |  NULL |   NULL |    NULL |     3.23 |        3.23 |\r\n| nsp05   |       52 | Mantenimiento del servidor |  NULL |   0.18 |    NULL |     NULL |        0.18 |\r\n| nsp05   |       53 | Mantenimiento a redmine    |  NULL |   0.53 |    NULL |     NULL |        0.53 |\r\n| nsp06   |        3 | Elaborar el visualzador de |  NULL |   0.23 |    NULL |     NULL |        0.23 |\r\n| nsp06   |       28 | Evitar que se tome mas de  |  NULL |   0.25 |    NULL |     NULL |        0.25 |\r\n| nsp06   |       55 | Actualizar el porcentaje d |  NULL |   1.50 |    NULL |     NULL |        1.50 |\r\n| nsp08   |       39 | Asistencia remota          |  NULL |   1.38 |    NULL |     NULL |        1.38 |\r\n+---------+----------+----------------------------+-------+--------+---------+----------+-------------+\r\n<\/pre>\n<p>Es todo! Luego con ese resultado es f\u00e1cil crear un peque\u00f1o reporte diario\/semanal sobre las horas utilizadas por cada usuario.<\/p>\n<div class=\"sharedaddy sd-sharing-enabled\"><div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\"><h3 class=\"sd-title\">Compartelo:<\/h3><div class=\"sd-content\"><ul><li class=\"share-facebook\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-facebook-665\" class=\"share-facebook sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2014\/08\/consultas-de-referencias-cruzadas-en-mysql\/?share=facebook\" target=\"_blank\" title=\"Haz clic para compartir en Facebook\"><span>Facebook<\/span><\/a><\/li><li class=\"share-twitter\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-twitter-665\" class=\"share-twitter sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2014\/08\/consultas-de-referencias-cruzadas-en-mysql\/?share=twitter\" target=\"_blank\" title=\"Haz clic para compartir en Twitter\"><span>Twitter<\/span><\/a><\/li><li><a href=\"#\" class=\"sharing-anchor sd-button share-more\"><span>M\u00e1s<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><div class=\"sharing-hidden\"><div class=\"inner\" style=\"display: none;\"><ul><li class=\"share-email\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-email sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2014\/08\/consultas-de-referencias-cruzadas-en-mysql\/?share=email\" target=\"_blank\" title=\"Haz clic para enviar por correo electr\u00f3nico a un amigo\"><span>Correo electr\u00f3nico<\/span><\/a><\/li><li class=\"share-print\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-print sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2014\/08\/consultas-de-referencias-cruzadas-en-mysql\/\" target=\"_blank\" title=\"Haz clic para imprimir\"><span>Imprimir<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-linkedin\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-linkedin-665\" class=\"share-linkedin sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2014\/08\/consultas-de-referencias-cruzadas-en-mysql\/?share=linkedin\" target=\"_blank\" title=\"Haz clic para compartir en LinkedIn\"><span>LinkedIn<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><\/div><\/div><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>Hace alg\u00fan tiempo que uso Redmine para gestionar proyectos, la herramienta en general es buena pero a veces necesitaba de reportes diarios de tiempo utilizado por los miembros del proyecto. En este punto se me ocurri\u00f3 si podr\u00eda lograr una &hellip; <a href=\"https:\/\/www.latindevelopers.com\/ivancp\/2014\/08\/consultas-de-referencias-cruzadas-en-mysql\/\">Sigue leyendo <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n<div class=\"sharedaddy sd-sharing-enabled\"><div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\"><h3 class=\"sd-title\">Compartelo:<\/h3><div class=\"sd-content\"><ul><li class=\"share-facebook\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-facebook-665\" class=\"share-facebook sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2014\/08\/consultas-de-referencias-cruzadas-en-mysql\/?share=facebook\" target=\"_blank\" title=\"Haz clic para compartir en Facebook\"><span>Facebook<\/span><\/a><\/li><li class=\"share-twitter\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-twitter-665\" class=\"share-twitter sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2014\/08\/consultas-de-referencias-cruzadas-en-mysql\/?share=twitter\" target=\"_blank\" title=\"Haz clic para compartir en Twitter\"><span>Twitter<\/span><\/a><\/li><li><a href=\"#\" class=\"sharing-anchor sd-button share-more\"><span>M\u00e1s<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><div class=\"sharing-hidden\"><div class=\"inner\" style=\"display: none;\"><ul><li class=\"share-email\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-email sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2014\/08\/consultas-de-referencias-cruzadas-en-mysql\/?share=email\" target=\"_blank\" title=\"Haz clic para enviar por correo electr\u00f3nico a un amigo\"><span>Correo electr\u00f3nico<\/span><\/a><\/li><li class=\"share-print\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-print sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2014\/08\/consultas-de-referencias-cruzadas-en-mysql\/\" target=\"_blank\" title=\"Haz clic para imprimir\"><span>Imprimir<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-linkedin\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-linkedin-665\" class=\"share-linkedin sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2014\/08\/consultas-de-referencias-cruzadas-en-mysql\/?share=linkedin\" target=\"_blank\" title=\"Haz clic para compartir en LinkedIn\"><span>LinkedIn<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><\/div><\/div><\/div><\/div><\/div>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":""},"categories":[7],"tags":[17,12,30],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1tEO5-aJ","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/posts\/665"}],"collection":[{"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/comments?post=665"}],"version-history":[{"count":2,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/posts\/665\/revisions"}],"predecessor-version":[{"id":667,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/posts\/665\/revisions\/667"}],"wp:attachment":[{"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/media?parent=665"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/categories?post=665"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/tags?post=665"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}