【问题标题】:Alias the sum of two columns in a DBIx::Class resultset别名 DBIx::Class 结果集中两列的总和
【发布时间】:2014-03-30 04:58:56
【问题描述】:

选择 me.id、me.date_created、me.date_updated、me.yes、 me.name, me.description, me.currency, me.locked, me.skip, me.uri_part,me.user_id, 是 + 货币作为重量

根据我的想法,我有 ((weight

如何在 DBIx::Class 中生成该查询而不使用像这样的文字 SQL:

    my $query = $rs->search({},
    {
        '+select' => \[
            'yes + currency as weight',
        ],
        rows => 1,
        order_by => { -desc => [qw/weight name/] },
        having => {
            weight => { '<' => $self->yes + $self->currency },
        },
    });
    use Data::Dumper;
    warn Dumper($query->as_query);

我尝试使用 -as,但是,它似乎只对处理从函数生成的列有用,因为这样:

'+select' =>  {
  'yes + currency', '-as' => 'weight'
}

产生错误

"匿名哈希中的奇数个元素在 /data/TGC/lib/TGC/DB/Result/Idea.pm 第 105 行,第 1000 行。 DBIx::Class::SQLMaker::_recurse_fields():选择参数格式错误 - 哈希中的键太多:SCALAR(0xbf14c40),weight"

【问题讨论】:

    标签: perl alias dbix-class


    【解决方案1】:

    “+as”应与“+select”处于同一级别

    $idea = $rs->search({-and => [
        name   => { '<' => $self->name },
    ]},
    {
        '+select' => [
            'yes + currency'
        ],
        '+as' => [qw/weight/],
        rows => 1,
        order_by => ['weight', 'name'],
        having => {
            weight => { '<' => $self->yes + $self->currency },
        },
    })->single;
    

    【讨论】:

    • +as 不会创建 select this as that from table 语法。来自ResultSet docs的“as”属性与SQL端AS无关。详见“选择”。
    • @alex 看起来不太对劲。你看过由此生成的 SQL 吗?
    • @alex,如果您阅读下面引用的代码示例,您会看到“注意 as 属性与 SQL 语法 SELECT foo AS bar 完全无关",然后它会向您展示如何控制列名。我确实花时间尝试了您的答案,但它没有生成正确的 SQL 语法。
    • @perlDreamer 纯 SQL 与 DBIx::Class 结果无关。如果 DBIx::Class 无论如何都要重命名,为什么还需要特定的 SQL 列名?
    【解决方案2】:

    可能是我在 SQL 抽象表达式中能想到的最惯用的东西,不用太费劲:

    #!/usr/bin/env perl
    use Modern::Perl;
    
    use MySchema;
    use Data::Dumper;
    
    my $schema = MySchema->connect('dbi:SQLite:example.db');
    
    my $rs = $schema->resultset('Sample')->search(
      {
         weight => { '<' => 5 },
      },
      {
        '+select' => [
            { '' => \'`me`.`yes` + `me`.`currency`', -as => 'weight' }
        ]
      }
    );
    
    
    say Dumper( $rs->as_query() );
    

    这是对列名的人为包装,但它确实起到了作用。只是不知道有什么方法可以在这里抽象+。但还是:

    '(SELECT me.name, me.yes, me.currency, (me.yes + me.currency) AS weight FROM sample me WHERE (weight

    除非您只是使用惯用的 perl,在这种情况下:

    { '' => \(join " + ", qw/`me`.`yes` `me`.`currency`/), -as => 'weight' }
    

    但考虑到这两种形式都比文字字符串长,这两种方式似乎有点做作。

    另请注意,weightWHERE 中而不是 HAVING 中引用,这是因为 在各种 SQL 引擎上崩溃。

    【讨论】:

    • 我更新了原始查询以修复基本 SQL 语法问题。最重要的是,我认为我们可能正在运行不同版本的 SQL::Abstract 或 DBIx::Class,因为我没有得到与您相同的查询(在使用您建议的子句修改原始后):SELECT @987654325 @.id, me.date_created, me.date_updated, me.yes, me.@9876543@34@, @987654336., @987654336., @9876 currency, me.locked, me.skip, me.uri_part, me.user_id, (@9876543449@.@9876543447@.@98765) weight 来自ideas me 拥有weight weight DESC、name DESC LIMIT 订购?)
    • 你是在说报价吗?那是因为您实现了哪个“DBI 驱动程序”。我所说的HAVING不会每个 数据库后端得到支持。因此,即使它生成了,如果您切换数据库,它也可能炸毁
    • @perlDreamer 忘记在评论中标记你
    • 我只需要支持 MySQL。所以吃了我的报价。仔细看,是'me'.'yes+me'.'currency' SQL Abstract 吃了加号。
    • @perlDreamer 是的。它为 MySQL 做到了这一点。因此,请自己按字面意思引用字符串。 "me.yes + me.currency" 不能做任何其他事情,因为它以 one 字符串文字的形式出现。那么 SO 将使用引号,但你知道我的意思。我希望
    猜你喜欢
    • 2011-12-24
    • 2011-06-27
    • 2011-07-19
    • 1970-01-01
    • 2015-04-04
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 2011-07-09
    相关资源
    最近更新 更多