Sequelize:加入两次同桌

问题描述 投票:6回答:3

Background:

我有一张桌子UsersUserlang有一对多的关系。例如:

 userlang.id userlang.userid userlang.lang     
+-----------+---------------+-------------+
 1            1              EN
 2            1              FR
 3            1              IT
 4            2              EN
 5            2              DE
 6            3              IT

我想选择至少有一个userlang.lang=EN.的所有用户及其用户

所以,我不能使用以下查询:

Select USERS.id from USERS inner join USERLANG on USERS.ID=USERLANG.USERID where USERLANG.LANG="EN"

因为它只会选择Userlangs行和lang="EN",而我想选择每个用户的所有userlang行,其中至少有一行有lang="EN"

我已经能够用SQL以两种方式编写这样的查询:

using sub queries:

Select * 
from USERS inner join USERLANG on USERS.ID=USERLANG.USERID
where USERS.ID in (
    Select USERS.id 
    from USERS inner join USERLANG on USERS.ID=USERLANG.USERID
    where USERLANG.LANG="EN"
)

虽然内部查询将仅使用lang="EN"选择userlang行,但外部查询将为这些用户选择所有userlangs

using two inner joins of the same table:

Select * 
from USERS innerjoin USERLANG as FILTER on FILTER.userid=USERS.userid
inner join USERLANG on USERLANG.userid=FILTER.userid
where FILTER.lang="EN"

问题:将它们移植到sequelize上

我完全无法在sequelize上编写子查询:我想避免编写纯SQL,因为它可能会打开可能的注入攻击。

这是我失败的尝试,因为'FILTER'与USer没有关系而产生错误:

models.User.findAll({
    include:[models.Userlang,{model:models.Userlang,as:'FILTER'}] 
})
sql node.js postgresql sequelize.js
3个回答
1
投票
       select userid,lang 
       from t 
       where userid in ( 
                          select userid 
                          from t  where lang="en" 
                          group by userid having count(lang)>=1)

    select a.userid,a.lang 
    from t a left join ( select userid,lang from t where lang ="en") b  
    on a.userid=b.userid 
    where b.lang is not null

不确定你的问题是什么,但也可以分两步完成相同的结果;用temptable替换子查询。


1
投票

尝试使用某些别名定义您的关联:

            List.belongsTo(Task, {
              as: 'dailyTask',
              foreignKey: 'dailyTask'
            });

            List.belongsTo(Task, {
               as: 'weeklyTask',
               foreignKey: 'weeklyTask'
            });

创建者的例子是在这个链接:https://github.com/sequelize/sequelize/issues/3678


0
投票

这是一个非常古老的帖子,但希望这给某人一个有用的答案。有很多方法可以实现这一点,包括一些原始的续集选项。

但是,假设这是一个可重用的引用,我会尝试将[USERLANG]关联到[USERLANG]并基于此进行查询。这将修改模型,因此对于一次性查询可能有点多。

models.UserLang.hasMany(models.UserLang, {as: 'Filter', foreignKey: 'UserId', targetKey: 'UserId'});

models.User.findAll({
    include:[{ model: models.Userlang,
        required: true,
        include:[{ model: models.Userlang,
            required: true, // redundant
            as: 'Filter',
            where: { lang='EN' }
        }]
    }]
})

您还可以在attributes列表中放置原始SQL子查询,并使用where子句根据结果进行过滤。这将是一个不需要修改模型的一次性解决方案。但这确实可以追溯到你对原始SQL的厌恶。

© www.soinside.com 2019 - 2024. All rights reserved.