在CASE语句中使用LIKE的GROUP_CONCAT列别名

时间:2013-01-04 02:50:43

标签: mysql view case group-concat

这里的想法是GROUP_CONCAT从连接到option_stock和options表的stock表中编译一个选项代码列表,按库存id分组。 一个示例行是这样的:

Name                Options             Transmission
'Holden Commodore' '111, 145, 166, 188' 'Auto' 

这个视图可以正常工作,但我不禁觉得有更优雅的解决方案吗?

CREATE VIEW stock_view AS
    (select s.description AS Name,
    group_concat(o.option_code order by o.option_code ASC separator ', ') 
    AS Options, 
    (case
        WHEN group_concat(o.option_code) LIKE '%111%' then 'Auto'
        WHEN group_concat(o.option_code) LIKE '%112%' then 'Manual'
        else 'Other'
    end) as Transmission
    from stock s
    join option_stock ost ON s.id = ost.stock_id
    join options o ON o.id = ost.option_id
    group by s.id)

我正试图避免在CASE困境中使用这个丑陋的看起来的GROUP_CONCAT,但是如果我在case语句中使用它,那么我会收到一条错误,说明Options字段不存在:

WHEN `Options` LIKE '%111%' then 'Auto'

我知道为什么会抛出错误 - 这是因为你不能以这种方式使用另一列的别名。但它有办法吗?

4 个答案:

答案 0 :(得分:1)

这些对我来说似乎不够可靠:

WHEN group_concat(o.option_code) LIKE '%111%' ...
WHEN group_concat(o.option_code) LIKE '%112%' ...

LIKE '%111%'会匹配,例如'111222, 145, 166, 188''111, 145, 166, 188'一样{。}}。当然,除非只有3个字符的代码,否则您不希望很快改变。

尽管如此,我可能会使用不同的技术,很可能是条件COUNT或SUM。例如:

(CASE
    WHEN SUM(o.option_code = '111') > 0 THEN 'Auto'
    WHEN SUM(o.option_code = '112') > 0 THEN 'Manual'
    ELSE 'Other'
END) AS Transmission

另请注意,在您的特定情况下,以下(尽管相当具体)解决方案也应该起作用:

IFNULL(
    MIN(CASE o.option_code WHEN '111' THEN 'Auto' WHEN '112' THEN 'Manual' END),
   'Other'
) AS Transmission

即。如果'111'或由于某种原因在同一组行的代码中找到'111''112',则MIN()将返回'Auto',如果'112'僵尸不是'111',它将评估为'Manual'。否则它将为NULL,在这种情况下IFNULL()函数将评估为'Other'

答案 1 :(得分:0)

很难在没有实际表的情况下进行测试(实际上不能执行语句)但是这样的事情呢?

CREATE VIEW stock_view AS
(SELECT
    gc.Name,
    gc.Options,
    (case
        WHEN gc.Options LIKE '%111%' then 'Auto'
        WHEN gc.Options LIKE '%112%' then 'Manual'
        else 'Other'
    end) as Transmission
FROM
    (select 
        s.description AS Name,
        group_concat(o.option_code order by o.option_code ASC separator ', ') AS Options
    from 
        stock s
        join option_stock ost ON s.id = ost.stock_id
        join options o ON o.id = ost.option_id
    group by 
        s.id) gc);

答案 2 :(得分:0)

进行单独的连接以确定传输类型:

CREATE VIEW stock_view AS
select
    s.description AS Name,
    group_concat(o.option_code order by o.option_code separator ', ') AS Options,
    if(t.option_code = '111', 'Auto', 'Manual') as Transmission
from stock s
join option_stock ost ON s.id = ost.stock_id
join options o ON o.id = ost.option_id
left join options t on t.id = ost.option_id 
     and option_code in ('111', '112')
group by s.id

只有一行将从传输连接中加入(汽车不能同时为自动和手动),这种方法可以避免所有这些子查询。

使连接成为 left 连接意味着缺少传输选项将显示为手动。您可以通过添加null测试来调整它以获得默认值。

答案 3 :(得分:0)

您必须创建两个单独的 VIEWS ,因为 MySQL 不支持 VIEW 中的子查询。

试试这个:

CREATE VIEW stock_view AS
  SELECT s.description AS sname, 
         GROUP_CONCAT(o.option_code ORDER BY o.option_code SEPARATOR ', ')  AS soptions 
  FROM stock s
  INNER JOIN option_stock ost ON s.id = ost.stock_id
  INNER JOIN OPTIONS o ON o.id = ost.option_id
  GROUP BY s.id;

CREATE VIEW stock_view1 AS 
  SELECT sname, soptions, 
         (CASE WHEN FIND_IN_SET('111', soptions) THEN 'Auto'
               WHEN FIND_IN_SET('112', soptions) THEN 'Manual'
               ELSE 'Other'
         END) AS Transmission
  FROM stock_view;