如何一次从三个表中返回行?

时间:2015-10-29 11:29:37

标签: sql node.js postgresql sequelize.js

如何将这三个查询合并为一个?

1

SELECT "Skills"."name", "Skills"."id", "TrainerScores"."fellow_uid", MIN("TrainerScores"."score") AS "score"
FROM "TrainerScores"
INNER JOIN "Skills" ON "TrainerScores"."skill_id" = "Skills"."id"
WHERE "TrainerScores"."fellow_uid" = 'google:105697533513134511631'
AND DATE("TrainerScores"."created_at") BETWEEN '2015-10-01' AND '2015-10-30'
GROUP BY "Skills"."name", "Skills"."id", "TrainerScores"."fellow_uid"

2

Select "Skills"."name", "Skills"."id", MIN("PeerScores"."score") AS "score"
FROM "PeerScores"
LEFT OUTER JOIN "Skills" ON "PeerScores"."skill_id" = "Skills"."id"
WHERE "PeerScores"."evaluatee_uid" = 'google:105697533513134511631'
AND DATE("PeerScores"."created_at") BETWEEN '2015-10-01' AND '2015-10-30'
GROUP BY "Skills"."name", "Skills"."id"

3

Select "Skills"."name", "Skills"."id", MIN("SelfScores"."score") AS "score"
FROM "SelfScores"
LEFT OUTER JOIN "Skills" ON "SelfScores"."skill_id" = "Skills"."id"
WHERE "SelfScores"."fellow_uid" = 'google:105697533513134511631'
AND DATE("SelfScores"."created_at") BETWEEN '2015-10-01' AND '2015-10-30'
GROUP BY "Skills"."name", "Skills"."id"

我想将此作为报告使用,我不想在任何时候想要获取数据时调用每个查询。

3 个答案:

答案 0 :(得分:3)

备选方案1,只是一个巨大的UNION ALL

SELECT "Skills"."name", "Skills"."id", "TrainerScores"."fellow_uid", MIN("TrainerScores"."score") AS "score"
FROM "TrainerScores"
INNER JOIN "Skills" ON "TrainerScores"."skill_id" = "Skills"."id"
WHERE "TrainerScores"."fellow_uid" = 'google:105697533513134511631'
AND DATE("TrainerScores"."created_at") BETWEEN '2015-10-01' AND '2015-10-30'
GROUP BY "Skills"."name", "Skills"."id", "TrainerScores"."fellow_uid"

UNION ALL

Select "Skills"."name", "Skills"."id", NULL, MIN("PeerScores"."score") AS "score"
FROM "PeerScores"
LEFT OUTER JOIN "Skills" ON "PeerScores"."skill_id" = "Skills"."id"
WHERE "PeerScores"."evaluatee_uid" = 'google:105697533513134511631'
AND DATE("PeerScores"."created_at") BETWEEN '2015-10-01' AND '2015-10-30'
GROUP BY "Skills"."name", "Skills"."id"

UNION ALL

Select "Skills"."name", "Skills"."id", NULL, MIN("SelfScores"."score") AS "score"
FROM "SelfScores"
LEFT OUTER JOIN "Skills" ON "SelfScores"."skill_id" = "Skills"."id"
WHERE "SelfScores"."fellow_uid" = 'google:105697533513134511631'
AND DATE("SelfScores"."created_at") BETWEEN '2015-10-01' AND '2015-10-30'
GROUP BY "Skills"."name", "Skills"."id"

答案 1 :(得分:3)

基本上,使用UNION ALL之类的WITH vals AS (SELECT timestamp '2015-10-01 00:00' AS ts_low -- incl. lower bound , timestamp '2015-10-31 00:00' AS ts_hi -- excl. upper bound , text 'google:105697533513134511631' AS uid) SELECT s.name, sub.* FROM ( SELECT skill_id AS id, min(score) AS score, 'T' AS source FROM "TrainerScores", vals v WHERE fellow_uid = v.uid AND created_at >= v.ts_low AND created_at < v.ts_hi GROUP BY 1 UNION ALL SELECT skill_id, min(score), 'P' FROM "PeerScores", vals v WHERE evaluatee_uid = v.uid AND created_at >= v.ts_low AND created_at < v.ts_hi GROUP BY 1 UNION ALL SELECT skill_id, min(score), 'S' FROM "SelfScores", vals v WHERE fellow_uid = v.uid AND created_at >= v.ts_low AND created_at < v.ts_hi GROUP BY 1 ) sub JOIN "Skills" s USING (id); @jarlh already provided章中手册中的详细信息。

但是 更多 。我的教育猜测,你真的想要这个:

LEFT [OUTER] JOIN

重点

  • 首先我修剪了你的语法噪音(可能由你的ORM产生),使其具有人类可读性:删除多余的双引号,添加表别名,修剪干扰词......

  • 您对LEFT JOIN的使用被破坏了,因为您对左表的列进行了过滤,这会抵消[INNER] JOIN。替换为WHERE

  • WITH子句中使用"Combining Queries"表达式,或者您的查询不能使用普通索引,对于大表来说会非常慢。相关:

  • 在CTE(uid子句)中提供 一次 参数 - 在您传递{{1}的预准备语句中不需要而是,ts_lowts_hi作为参数。

  • 我从第一个查询的输出中删除了"TrainerScores"."fellow_uid"以简化查询。无论如何,这只是你的输入参数。

  • 您可以在加入"Skills" 之前将 / LI>

  • 我添加了一列source来表示每行的来源。

除此之外:您似乎想要匹配整个2015年10月,但之后您将其排除在10月31日。这是故意的吗?

答案 2 :(得分:1)

我提出的解决方案完全符合您的要求,但它确实有效。使用raw查询,您可以运行并获取多个查询的结果,如下所示:

var sequelize = require('./libs/pg_db_connect');

var query = "SELECT Skills.name, Skills.id, TrainerScores.fellow_uid, MIN(TrainerScores.score) AS score
FROM TrainerScores
INNER JOIN Skills ON TrainerScores.skill_id = Skills.id
WHERE TrainerScores.fellow_uid = 'google:105697533513134511631' AND DATE(TrainerScores.created_at) BETWEEN '2015-10-01' AND '2015-10-30'
GROUP BY Skills.name, Skills.id, TrainerScores.fellow_uid";


sequelize.query(query, {
   type: sequelize.QueryTypes.SELECT
}).success(function (query1) {
   done = _.after(query1.length, function () {
      callback(query1)
   })

   query = "Select Skills.name, Skills.id, MIN(PeerScores.score) AS score
        FROM PeerScores
        LEFT OUTER JOIN Skills ON PeerScores.skill_id = Skills.id
        WHERE PeerScores.evaluatee_uid = 'google:105697533513134511631' AND DATE(PeerScores.created_at) BETWEEN '2015-10-01' AND '2015-10-30'
        GROUP BY Skills.name, Skills.id";

   sequelize.query(query, {
      type: sequelize.QueryTypes.SELECT
   }).success(function (query2) {

      query = "Select Skills.name, Skills.id, MIN(SelfScores.score) AS score
        FROM SelfScores
        LEFT OUTER JOIN Skills ON SelfScores.skill_id = Skills.id
        WHERE SelfScores.fellow_uid = 'google:105697533513134511631' AND DATE(SelfScores.created_at) BETWEEN '2015-10-01' AND '2015-10-30'
        GROUP BY Skills.name, Skills.id";

      sequelize.query(query, {
         type: sequelize.QueryTypes.SELECT
      }).success(function (query3) {
         console.log(query1); // show the returns of query 1
         console.log(query2); // show the returns of query 2
         console.log(query3); // show the returns of query 3
      });

success的{​​{1}}函数的结果也可以存储在json变量中。