【问题标题】:Additional conditions in JOINJOIN 中的附加条件
【发布时间】:2015-01-12 01:56:33
【问题描述】:

我有包含文章和用户的表格,两者都有到第三个表格的多对多映射 - 读取。

我在这里要做的是获取特定用户的所有未读文章(user_id 不存在于表 reads 中)。 我的查询正在获取所有文章,但已标记阅读的文章,如果可以,我可以将它们过滤掉(user_id 字段包含相关用户的 id)。

我有一个这样的 SQL 查询:

SELECT articles.id, reads.user_id 
FROM articles 
LEFT JOIN 
reads 
ON articles.id = reads.article_id AND reads.user_id = 9 
ORDER BY articles.last_update DESC LIMIT 5;

产生以下结果:

    articles.id    | reads.user_id
-------------------+-----------------
 57125839          |       9
 57065456          |
 56945065          |
 56945066          |
 56763090          |
(5 rows)

这很好。这就是我想要的。

我想使用我的文章模型在 Catalyst 中获得相同的结果,但我找不到任何选项来向 JOIN 子句添加条件。

您知道如何将AND X = Y 添加到 DBIx JOIN 中吗?

我知道这可以通过自定义结果源和虚拟视图来完成,但我还有其他一些可以从中受益的查询,我想避免为每个查询创建虚拟视图。

谢谢, 粤语

【问题讨论】:

  • 您是否尝试将其添加为“标准”where 子句?
  • 是的。 “标准” where 子句将仅过滤用户阅读的那些文章(存在于 reads 表中)。它不会显示相应读取表条目为 NULL 的文章。使用 AND 和 LEFT JOIN 会给我所有的文章。如果文章被读取,则设置 user_id 字段,否则为 NULL。
  • 如果要获取带有reads.user_id = NULL的文章,则不能在查询中使用AND reads.user_id = 9条件。
  • @kordirko 当然可以。只要它在 JOIN 子句中。 SELECT articles.id, reads.user_id FROM articles LEFT JOIN reads ON reads.article_id = articles.id AND reads.user_id = 9 ORDER BY articles.last_update DESC LIMIT 5; 身份证 | user_id ----------+--------- 57125839 | 9 57065456 | 56945065 | 56945066 | 56763090 |抱歉,我无法格式化此评论...
  • @kordirko 不幸的是,这不起作用,因为它会过滤掉其他用户(除了 id 9)阅读的文章。我原来的问题中的查询正在做我想做的事。我只想使用 DBIx/Catalyst 模型做同样的事情。

标签: perl postgresql catalyst dbix-class


【解决方案1】:

我什至不知道Catalyst 是什么,但我可以破解 SQL 查询:

select articles.id, reads.user_id 
from
    articles 
    left join 
    (
        select *
        from reads
        where user_id = 9
    ) reads on articles.id = reads.article_id
order by articles.last_update desc 
limit 5;

【讨论】:

  • 谢谢。 Catalyst 是基于 MVC perl 的 Web 框架。鉴于这不是严格的催化剂答案,我不会标记为已解决。我会调查的。也许这个解决方法会有所帮助:)对不起,我还不能投票,没有足够的声誉:(
【解决方案2】:

我有一个解决方案。

这不是直接的,但它比虚拟视图更好。

http://search.cpan.org/dist/DBIx-Class/lib/DBIx/Class/Relationship/Base.pm#condition

上面描述了如何在 JOIN 子句中使用条件。 但是,我的案例在这些条件下需要一个变量,默认情况下在模型中不可用。 因此,绕过一些模型概念并为其引入变量,我们有以下内容。

在模型文件中

our $USER_ID;
__PACKAGE__->has_many(
    pindols => "My::MyDB::Result::Read",
    sub {
        my $args = shift;

        die "no user_id specified!" unless $USER_ID;

        return ({
            "$args->{self_alias}.id" => { -ident => "$args->{foreign_alias}.article_id" },
            "$args->{foreign_alias}.user_id" => { -ident => $USER_ID },
        });

    }
);

在控制器中

$My::MyDB::Result::Article::USER_ID = $c->user->id;
$articles = $channel->search(
    { "pindols.user_id" => undef } , 
    { 
        page => int($page),
        rows => 20, 
        order_by => 'last_update DESC', 
        prefetch =>  "pindols" 
    }
);

将获取所有未读文章并产生以下 SQL。

SELECT me.id, me.url, me.title, me.content, me.last_update, me.author, me.thumbnail, pindols.article_id, pindols.user_id FROM (SELECT me.id, me.url, me.title, me.content, me.last_update, me.author, me.thumbnail FROM articles me LEFT JOIN reads pindols ON ( me.id = pindols.article_id AND pindols.user_id = 9 ) WHERE ( pindols.user_id IS NULL ) GROUP BY me.id, me.url, me.title, me.content, me.last_update, me.author, me.thumbnail ORDER BY last_update DESC LIMIT ?) me LEFT JOIN reads pindols ON ( me.id = pindols.article_id AND pindols.user_id = 9 ) WHERE ( pindols.user_id IS NULL ) ORDER BY last_update DESC: '20'

当然你可以跳过分页,但我的代码中有它,所以我把它包含在这里。

特别感谢 irc.perl.org 上 #dbix-class 和 https://blog.afoolishmanifesto.com/posts/dbix-class-parameterized-relationships/deg

谢谢, 粤语

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-05
    • 2014-08-26
    • 2012-06-28
    • 2013-05-26
    • 1970-01-01
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    相关资源
    最近更新 更多