2014-11-14 80 views
1

我有包含文章和用戶的表格,它們都有多對多映射到第三個表格 - 讀取。JOIN中的其他條件

我在這裏要做的是爲特定用戶獲取所有未讀文章(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?

我知道這可以通過自定義資源和虛擬視圖來完成,但我還有其他一些可以從中受益的查詢,並且我想避免爲它們中的每個創建虛擬視圖。

感謝, 坎託

+0

您是否嘗試過將其添加爲「標準」 where子句? – 2014-11-14 16:42:18

+1

是的。 「標準」where子句將只過濾那些由用戶讀取的文章(存在於讀取表中)。它不會顯示相應的讀取表項爲NULL的文章。 使用AND和LEFT JOIN會給我所有的文章。如果文章被讀取,User_id字段將被設置,如果不是,則它將是NULL。 – canto 2014-11-14 18:24:02

+0

如果要使用'reads.user_id = NULL'獲取文章,則不能在查詢中使用'AND reads.user_id = 9'條件。 – krokodilko 2014-11-14 18:38:44

回答

1

我得到了一個解決方案。

這不是直截了當,但它比虛擬視圖更好。

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' 

當然,您可以跳過分頁,但是我已將它放在代碼中,因此我將它包含在此處。

特別感謝deg來自irc.perl.org上的#dbix-class和https://blog.afoolishmanifesto.com/posts/dbix-class-parameterized-relationships/

感謝, 坎託

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; 
+0

謝謝。催化劑是基於MVC perl的web框架。 鑑於它不是嚴格的催化劑答案,我不會標記爲已解決。 我會研究它。也許這種解決方法將有助於:) 對不起,但我不能投票了,沒有足夠的聲譽:( – canto 2014-11-14 19:21:34