首页 > 解决方案 > 有没有办法将这两个查询合并为一个?

问题描述

我正在创建一个测验应用程序,对于主页,我希望用户能够看到他们玩过的测验以及管理员和他们自己编写的测验。但是,我正在努力将这些组合成一个查询。我已经尝试过加入,但是由于我在第二个查询中使用了 where 子句,所以我无法加入它们。任何帮助将不胜感激。谢谢!

select quiz.title, quiz.quizid 
from quiz 
where id = $1 
or id = 'admin' 
order by quiz.id desc

这将返回某个 id 和 admin 写入的所有值。

select distinct quiz.quizid,quiz.title 
from quiz 
    inner join played on quiz.quizid = played.quizid

此查询返回用户玩过的所有测验

标签: sqlpostgresqlrelational-databasepsql

解决方案


在我看来你需要 LEFT JOIN 播放而不是 INNER JOIN

使用左连接意味着played.quizid对于尚未玩过的测验将为空,这意味着您可以CASE WHEN played.quizid IS NULL then 'not played' ELSE 'played' END as played_or_not在您的选择中使用类似的东西..

小心不要使用子句played中的任何列WHERE,因为它会导致 LEFT JOIN 恢复为 INNER(您将要求数据库将 NULL 与某些东西进行比较,这始终是错误的)

SELECT * 
FROM L LEFT JOIN R ON L.id = R.id
WHERE R.somecolmumn = 'somevalue' --no; it will discard the NULLs the left join introduces

保留空值或排除 ON 中的限制的规定:

SELECT * 
FROM L LEFT JOIN R ON L.id = R.id AND R.somecolmumn = 'somevalue' --yes

SELECT * 
FROM L LEFT JOIN R ON L.id = R.id
WHERE 
  (R.somecolmumn = 'somevalue' OR R.somecolumn IS NULL) --yes, but only if somecolumn doesn't naturally contain NULL

根据评论编辑:

好的,因此解决此问题的最简单方法可能是两部分,因为进行的测验可能是他们自己的,管理员或某些随机用户的..

SELECT quizid FROM quiz WHERE author_userid = $1 OR author_userid = 'ADMIN'

得到他们自己和管理员的测验。

SELECT DISTINCT quizid FROM played WHERE player_userid = $1

获取他们玩过的测验列表。您可以将这些与 UNION 放在一起:

SELECT quizid FROM quiz WHERE author_userid = $1 OR author_userid = 'ADMIN'
UNION
SELECT DISTINCT quizid FROM played WHERE player_userid = $1

它是一列唯一的测验 ID。您可以再次加入测验以获取详细信息:

SELECT * 
FROM
(
  SELECT quizid FROM quiz WHERE author_userid = $1 OR author_userid = 'ADMIN'
  UNION
  SELECT DISTINCT quizid FROM played WHERE player_userid = $1

) show
INNER JOIN quiz ON quiz.quizid = show.quizid

但你确实失去了“它存在的原因”

如果您将所有测验一起连接到不同戏剧的左连接:

SELECT * 
FROM
  quiz
  LEFT JOIN (SELECT DISTINCT quizid FROM played WHERE played_userid = $1) plyd
  ON quiz.quizid = plyd.quizid
WHERE
  quiz.author_userid IN ('ADMIN', $1) --admin's or their own 
  OR
  plyd.quizid IS NOT NULL             --other ppl's quizzes they played

您可以通过查看谁编写它以及 plyd.quizid 是否为空(null = 他们没有玩过,not null = 他们玩过)的组合来找出为什么会出现测验


推荐阅读