2012-07-11 39 views
8

我没有想到会发现这很难,但我试图在MySQL中设置一个用户变量来包含一个值的数组。我不知道如何做到这一点,所以试着做一些研究,很惊讶地发现没有答案。我曾尝试:如何设置一个数组作为一个mysql用户变量

SET @billable_types = ['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 (@billable_types) 
      and tlg.task_id = mttl.id 
    group by start_date 
    order by start_date desc; 

将是帮助,非常感谢。


快进了一会儿,我结束了以下的快速和肮脏的解决方案,它并没有给我的灵活性,再使用阵列其他地方的代码,但嘿,这是一个不可充电管理任务,所以我不要我不想花更多的时间在它上面。

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似乎已经找到了最完美的解决方案(没有测试它自己还没有),但我正在写一些东西,呼吁这个下次我会记得测试一下吧!

+2

有没有这样的事情,像SQL中的数组 - 只有集合。不幸的是,你试图无法工作 - mysql将用你的“数组”的内容替换@billtable_types作为一个整体字符串,而不会将它视为一组单独的逗号分隔值。尝试使用'FIND_IN_SET()'函数代替'IN'运算符。 – 2012-07-11 03:10:30

回答

11

就找到了答案在这里: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

“in”关键字不存在错误代码:1064 您的SQL语法错误;查看与你的MySQL服务器版本相对应的手册,在'@billable_types'附近使用正确的语法)' – Mindwin 2014-02-05 14:17:28

0

正如马克B中提及的,存在MYSQL没有数组变量。

FIND_IN_SET解决方案的替代方案是使用选择UNION模拟阵列:

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

所以,你的查询将看起来像这样:

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

由于这个线程已经浮出水面,我将编辑我的原始问题并添加我最终做的事情。 – 2014-05-09 05:28:06

0

如果用户具有CREATE TABLE特权,则可以通过创建临时单列表来模拟数组。可以使用SELECT语句检索表中的一个或多个值。临时表会在会话结束时被删除,但一旦不再需要时,明确地删除它们是个好主意。

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; 
相关问题