2012-07-11 13 views
8

No esperaba encontrar esto tan difícil, pero estoy tratando de establecer una variable de usuario en MySQL para contener una matriz de valores. No tengo ni idea de cómo hacer esto, así que intenté investigar un poco y quedé bastante sorprendido de no encontrar respuesta. He tratado:cómo establecer una matriz como una variable de usuario de mysql

SET @billable_types = ['client1','client2','client3']; 

La razón es que me gustaría utilizar la variable en la siguiente declaración más adelante:

SELECT sum((time_to_sec(timediff(tlg.time_stop, tlg.time_start))/3600)) as billable_hours 
    from mod_tmlog_time_log tlg, mod_tmlog_task_list mttl 
    where date(tlg.time_start) >= @time_start 
      and date(tlg.time_stop) <= @time_stop 
      and mttl.type IN (@billable_types) 
      and tlg.task_id = mttl.id 
    group by start_date 
    order by start_date desc; 

estaría muy agradecido por la ayuda.


avance rápido de un tiempo, que terminó con la siguiente solución rápida y sucia, que no me da la flexibilidad de la reutilización de la matriz en otras partes del código, pero oye, una tarea de administración cargarse más así que Don No quiero pasar más tiempo en eso.

SELECT WEEKDAY(tlg.time_start) AS day_of_week, date(tlg.time_start) as start_date, 
          sum((time_to_sec(timediff(tlg.time_stop, tlg.time_start))/3600)) as billable_hours 
        from mod_tmlog_time_log tlg, mod_tmlog_task_list mttl 
        where date(tlg.time_start) >= @time_start 
          and date(tlg.time_stop) <= @time_stop 
          and mttl.type IN ('c1','c2','c3') 
          and tlg.task_id = mttl.id 
        group by start_date 
        order by start_date desc; 

joostschouten parece haber encontrado la solución más elegante (no probado yo mismo todavía) pero la próxima vez que estoy escribiendo algo que llama a esto voy a recordar para probarlo!

+2

no existen los arrays en SQL, solo hay conjuntos. Desafortunadamente, lo que intentas no funciona: mysql reemplazará @billtable_types con el contenido de tu "matriz" como una única cadena monolítica, y no lo considerará como un conjunto de valores separados por comas separados. Intenta usar la función 'FIND_IN_SET()' en lugar del operador 'IN'. –

Respuesta

11

acaba de encontrar la respuesta aquí: How to cycle with an array in MySQL?

set @billable_types = 'client1,client2,client3'; 
select * from mttl where find_in_set(mttl.type, @billable_types); 
+1

la palabra clave "en" no existe 'Código de error: 1064 Tiene un error en su sintaxis SQL; revise el manual que corresponde a su versión del servidor MySQL para la sintaxis correcta para usar cerca de 'en @billable_types) ' – Mindwin

0

Como se mencionó Marc B, no existe una variable de matriz en MySQL.

La alternativa a FIND_IN_SET solución es utilizar SELECT con UNIÓN para simular la matriz:

SELECT billable_type FROM (
    SELECT 'client1' AS billable_type UNION 
    SELECT 'client2' AS billable_type UNION 
    SELECT 'client3' AS billable_type) AS t 

Así que su voluntad consulta parece que:

SELECT sum((time_to_sec(timediff(tlg.time_stop, tlg.time_start))/3600)) as billable_hours 
    from mod_tmlog_time_log tlg, mod_tmlog_task_list mttl 
    where date(tlg.time_start) >= @time_start 
      and date(tlg.time_stop) <= @time_stop 
      and mttl.type IN (

      SELECT billable_type FROM (
       SELECT 'client1' AS billable_type UNION 
       SELECT 'client2' AS billable_type UNION 
       SELECT 'client3' AS billable_type) AS t 

     ) 
      and tlg.task_id = mttl.id 
    group by start_date 
    order by start_date desc; 
+0

Como este hilo ha vuelto a aparecer, editaré mi pregunta original y agregaré lo que terminé haciendo. –

0

Si el el usuario tiene el privilegio CREATE TABLE, una matriz se puede simular creando una tabla temporal de columna única. Un valor o valores en la tabla se pueden recuperar con una instrucción SELECT. Las tablas temporales se eliminan al final de la sesión, pero es una buena idea soltarlas explícitamente cuando ya no sean necesarias.

CREATE TEMPORARY TABLE billable_types (c VARCHAR(16)); 
INSERT INTO billable_types VALUES ('client1'), ('client2'), ('client3'); 

SELECT sum((time_to_sec(timediff(tlg.time_stop, tlg.time_start))/3600)) as billable_hours 
from mod_tmlog_time_log tlg, mod_tmlog_task_list mttl 
where date(tlg.time_start) >= @time_start 
     and date(tlg.time_stop) <= @time_stop 
     and mttl.type IN (SELECT * FROM billable_types) 
     and tlg.task_id = mttl.id 
group by start_date 
order by start_date desc; 

DROP TABLE billable_types; 
Cuestiones relacionadas