sql – 如何使用除`=`之外的其他运算符使DBIx :: Class连接表?

概要

我有一张成对的物品表.我想自己加入,所以我可以在单个查询中检索对的双方.它是有效的sql(我认为),sqlite引擎实际上接受它,但我无法获取DBIx :: Class咬住项目符号.

最小的例子

package Schema::Half;
use parent 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('half');
__PACKAGE__->add_columns(
  whole_id => { data_type => 'INTEGER' },half_id  => { data_type => 'CHAR'    },data     => { data_type => 'TEXT'    },);
__PACKAGE__->has_one(dual => 'Schema::Half',{
  'foreign.whole_id' => 'self.whole_id','foreign.half_id' => 'self.half_id',# prevIoUs line results in a '='
  # I'd like a '<>'
});

package Schema;
use parent 'DBIx::Class::Schema';
__PACKAGE__->register_class( 'Half','Schema::Half' );

package main;
unlink 'join.db';
my $s = Schema->connect('dbi:sqlite:join.db');
$s->deploy;

my $h = $s->resultset('Half');
$h->populate([
  [qw/whole_id half_id data  /],[qw/1        L       Bonnie/],[qw/1        R       Clyde /],[qw/2        L       Tom   /],[qw/2        R       Jerry /],[qw/3        L       Batman/],[qw/3        R       Robin /],]);
$h->search({ 'me.whole_id' => 42 },{ join => 'dual' })->first;

最后一行生成以下sql

SELECT me.whole_id,me.half_id,me.data
FROM half me
JOIN half dual ON ( dual.half_id = me.half_id AND dual.whole_id = me.whole_id )
WHERE ( me.whole_id = ? )

我试图使用DBIx :: Class join语法来获取<>操作符在dual.half_id和me.half_id之间,但尚未到目前为止.

我试过的东西

该文档提示sql :: Abstract-like语法.

我试着写这个has_one的关系:

__PACKAGE__->has_one(dual => 'Schema::Half','foreign.half_id' => { '<>' => 'self.half_id' },});

# Invalid rel cond val HASH(0x959cc28)

stringref后面的直sql不会使它成为:

__PACKAGE__->has_one(dual => 'Schema::Half','foreign.half_id' => \'<> self.half_id',});

# Invalid rel cond val SCALAR(0x96c10b8)

解决办法以及为什么他们对我来说不够

我可以通过复杂的search()调用获得正确的sql,并且没有定义的关系.这是非常难看的,(也)很多硬编码的sql.对于关系遍历的每个具体情况,它必须以不必要的方式模仿.

我可以通过添加一个other_half_id列并加入=来解决问题.显然是冗余数据.

我甚至试图通过专用视图添加它来避免所述冗余(CREATE VIEW AS SELECT *,opposite_of(side)AS dual FROM half …)而不是数据库模式,它的代码是冗余和丑陋的,moreso比基于search()的解决方法.最后我没有勇气让它工作.

希望sql

这是我正在寻找的那种sql.请注意,这只是一个例子:我真的希望通过关系完成,所以我可以使用它作为Half ResultSet访问器,除了一个search()的连接子句.

sqlite> SELECT * 
        FROM half l 
        JOIN half r ON l.whole_id=r.whole_id AND l.half_id<>r.half_id
        WHERE l.half_id='L';
1|L|Bonnie|1|R|Clyde
2|L|Tom|2|R|Jerry
3|L|Batman|3|R|Robin

旁注

我真的很自信,在我的全面扩大的情况下,但我很确定这不是问题.我以这种方式保留这个简单的例子,因为它也有助于保持代码大小小.

我坚持加入/关系路径,而不是复杂的搜索(),因为我有多个用途的关联,我没有找到任何“一刀切”的搜索表达式.

迟到更新

两年后的Answering my own question年以来,它以前是一个缺少的功能,从那时起就已经实现了.

解决方法

对于那些仍然感兴趣的人,它终于实现了0.08192或更早. (我目前在0.08192)

一个正确的语法是:

__PACKAGE__->has_one(dual => 'Schema::Half',sub {
  my $args = shift;
  my ($foreign,$self) = @$args{qw(foreign_alias self_alias)};
  return {
    "$foreign.whole_id" => { -ident => "$self.whole_id" },"$foreign.half_id" => { '<>' => { -ident => "$self.half_id" } },}
});

引用:DBIx::Class Extended Relationships on fREW Schmidt’s blog在哪里我首先阅读它.

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 &#39;EastRiver&#39; 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...