【问题标题】:Sequelize: join two times the same tableSequelize:两次加入同一张表
【发布时间】:2016-04-05 10:09:42
【问题描述】:

背景:

我有一个表 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"

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

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

使用子查询:

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" 的用户语言行,但外部查询将为此类用户选择所有userlangs

使用同一张表的两个内连接:

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,因为它会打开可能的注入攻击。

这是我失败的尝试,由于“过滤器”与用户没有关系而导致错误:

models.User.findAll({
    include:[models.Userlang,{model:models.Userlang,as:'FILTER'}] 
})

【问题讨论】:

  • 您提到子查询不适用于 Sequelize,但是您的联接查询呢?
  • @TimBiegeleisen,在问题的最后,我尝试加入查询。 Sequelize 会报错,因为 FILTER 与 ORM 模型中的 Users 没有关联。看来我无法进行任意连接。

标签: sql node.js postgresql sequelize.js


【解决方案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

不确定您的问题是什么,但也可以通过分两步来获得相同的结果;用临时表替换子查询。

【讨论】:

    【解决方案2】:

    尝试用一些别名来定义你的关联:

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

    创建者的示例在此链接中: https://github.com/sequelize/sequelize/issues/3678

    【讨论】:

      【解决方案3】:

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

      但是,假设这是一个可重用的参考,我会尝试将 [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 子查询(使用 sequelize.literal()),并使用 where 子句根据结果进行过滤。那将是一种不需要修改模型的一次性解决方案。但这确实可以追溯到您对原始 SQL 的厌恶。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-16
        • 1970-01-01
        • 1970-01-01
        • 2014-09-15
        • 2014-03-17
        • 1970-01-01
        • 2015-04-04
        • 2012-08-22
        相关资源
        最近更新 更多