我想从带有DBIx::Class
的表中检索行,并从同一个表中预取相应的行,其中列具有特定的其他值。我需要从计划A中获取所有作业(复制它们)并从计划B中检索所有相应的作业。
我已经编制了用于测试的表格,如下所示:
CREATE TABLE tasks (
id INTEGER
);
CREATE TABLE schedules (
id INTEGER
);
CREATE TABLE assignments (
id INTEGER,
scheduleId INTEGER,
taskId INTEGER,
worker TEXT,
FOREIGN KEY (scheduleId) REFERENCES schedules(id),
FOREIGN KEY (taskId) REFERENCES tasks(id)
);
计划1有一些任务,计划2有一些任务:
INSERT INTO tasks (id) VALUES (1);
INSERT INTO tasks (id) VALUES (2);
INSERT INTO schedules (id) VALUES (1);
INSERT INTO schedules (id) VALUES (2);
INSERT INTO assignments (id,scheduleId,taskId,worker) VALUES (1,1,1,"Alice");
INSERT INTO assignments (id,scheduleId,taskId,worker) VALUES (2,1,2,"Bob");
INSERT INTO assignments (id,scheduleId,taskId,worker) VALUES (3,2,1,"Charly");
这是一些返回所需结果的SQL:
SELECT * FROM assignments AS a1
LEFT OUTER JOIN assignments AS a2 ON
a2.scheduleId = 2 AND
a2.taskId = a1.taskId
WHERE a1.scheduleId = 1;
在SQLite中,这可以按预期工作:结果显示了来自计划1的每个作业的一行和来自计划2的相应作业。
id|scheduleId|taskId|worker|id|scheduleId|taskId|worker
1|1|1|Alice|3|2|1|Charly
1|1|2|Bob|NULL|NULL|NULL|NULL
到目前为止,我尝试使用DBIx :: Class的功能无效。这就是作业的类似:
package MyApp::Schema::Result::Assignment;
...
__PACKAGE__->has_many(
inAllSchedules => 'MyApp::Schema::Result::Assignment',
{
'foreign.taskId' => 'self.taskId',
}
);
以下代码正确连接行但仅返回来自计划1的行,这些行实际上具有计划2中的相应行:
my $assignments = $schema->resultset('Assignment')->search({
'inAllSchedules.scheduleId' => 2,
}, {
prefetch => 'inAllSchedules',
});
此代码也正确地correclty连接行并返回没有连接行的行,但我不知道如何过滤连接的行。我不想检索计划3等的行或只是任何其他行......
my $assignments = $schema->resultset('Assignment')->search(undef, {
join_type => 'left outer',
prefetch => 'inAllSchedules',
});
我无法编写特定关系,因为时间表A或B的ID仅在运行时给出。
如何生成给定的SQL代码或以其他方式检索数据?
答案 0 :(得分:3)
这看起来像custom join conditions的情况。下面的解决方案适用于您的有限示例,但可能需要针对您的实际应用进行调整。
__PACKAGE__->has_many(
'inAllSchedules' => "MyApp::Schema::Result::Assignment",
sub {
my $args = shift;
return {
"$args->{foreign_alias}.taskId" => { '-ident' => "$args->{self_alias}.taskId" },
"$args->{foreign_alias}.id" => { '<>' => { '-ident' => "$args->{self_alias}.id" } },
};
}
);
你会像这样使用它:
my $assignments = $schema->resultset("Assignment")->search({
'me.scheduleId' => 1,
'inAllSchedules.scheduleId' => [ 2, undef ],
},
{
'prefetch' => "inAllSchedules",
});