【问题标题】:Using GROUP_CONCAT column alias in CASE statement with LIKE在带有 LIKE 的 CASE 语句中使用 GROUP_CONCAT 列别名
【发布时间】:2012-12-18 11:52:30
【问题描述】:

这里的想法是 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'

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

【问题讨论】:

    标签: mysql view case group-concat


    【解决方案1】:

    如果没有实际的表很难测试(实际上无法执行语句),但是像这样的东西呢:

    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);
    

    【讨论】:

    • 这行得通吗?我不认为 SELECT 可以在视图中进入 FROM 内部?我用你的回答作为灵感,我创建了第二个视图 select s.id, 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在我的 stock_view 中,所以我可以只使用 when option_view.options LIKE '%111' THEN 'Auto' 抱歉格式化我不知道如何添加新行
    • 您对 FROM 中的子查询是正确的 - 抱歉,已经有一段时间了。
    【解决方案2】:

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

    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
    

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

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

    【讨论】:

      【解决方案3】:

      您必须创建两个单独的 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;
      

      【讨论】:

        【解决方案4】:

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

        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' bot 不是'111',它将评估为'Manual'。否则它将为 NULL,在这种情况下,IFNULL() 函数将评估为 'Other'

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-01-17
          • 1970-01-01
          • 2011-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多