草庐IT

MySQL 查询根据不同条件连接 4 个表

coder 2023-10-13 原文

我有 4 个表(为简洁起见,删除了相关的列):

CREATE TABLE `papers` (
   `paper_id` int(11) NOT NULL DEFAULT '0',
   PRIMARY KEY (`paper_id`)
);
INSERT INTO papers ( paper_id ) VALUES(1001);
INSERT INTO papers ( paper_id ) VALUES(1002);   
INSERT INTO papers ( paper_id ) VALUES(1003);
INSERT INTO papers ( paper_id ) VALUES(1004);
INSERT INTO papers ( paper_id ) VALUES(1005);
INSERT INTO papers ( paper_id ) VALUES(1006);

CREATE TABLE `questions` (
  `question_id` int(11) NOT NULL AUTO_INCREMENT,
  `type_id` int(11) NOT NULL,
  PRIMARY KEY (`question_id`)
);
INSERT INTO questions ( type_id ) VALUES(1);
INSERT INTO questions ( type_id ) VALUES(2);
INSERT INTO questions ( type_id ) VALUES(1);
INSERT INTO questions ( type_id ) VALUES(3);

CREATE TABLE `question_depends` (
  `question_id` int(11) NOT NULL,
  `depends_question_id` int(11) NOT NULL,
  `depends_answer_val` int(11) NOT NULL,
  PRIMARY KEY (`question_id`,`depends_question_id`)
);
INSERT INTO question_depends ( question_id, depends_question_id, depends_answer_val ) VALUES(3, 1, 0);
INSERT INTO question_depends ( question_id, depends_question_id, depends_answer_val ) VALUES(2, 1, 1);
INSERT INTO question_depends ( question_id, depends_question_id, depends_answer_val ) VALUES(3, 1, 1);

CREATE TABLE `answers` (
  `paper_id` int(11) NOT NULL,
  `question_id` int(11) NOT NULL,
  `answer_val` int(2) NOT NULL,
  PRIMARY KEY (`paper_id`,`question_id`)
); 
INSERT INTO answers ( paper_id, question_id, answer_val ) VALUES(1002, 1, 1);
INSERT INTO answers ( paper_id, question_id, answer_val ) VALUES(1002, 4, 0);
INSERT INTO answers ( paper_id, question_id, answer_val ) VALUES(1004, 1, 0);
INSERT INTO answers ( paper_id, question_id, answer_val ) VALUES(1004, 3, 1);
INSERT INTO answers ( paper_id, question_id, answer_val ) VALUES(1005, 1, 1);

我想提出一个查询来显示所有可能组合的所有数据:

  1. 所有的论文ID应该至少输出一次
  2. 给定的 paper_id 可能有也可能没有答案,可能有也可能没有依赖性
  3. 最终目标是查看每个依赖性问题是否已回答,如果是,答案 val 是否与每个论文 id 的依赖性答案 val 匹配,同时确定 paper_id 是否有依赖性问题以及是否有任何问题未回答(他们是否有依赖关系)
  4. 如果需要,我可以调整表格/数据

我接近了:

select P.paper_id as P_PID,
  A.paper_id as A_PID,
  A.question_id as A_QID,
  A.answer_val as A_VAL,
  QD.question_id as QD_QID,
  QD.depends_question_id AS QD_DQID,
  QD.depends_answer_val AS QD_VAL,
  Q.type_id AS Q_TYPE
from papers P
left join answers A on A.paper_id = P.paper_id
left join question_depends QD on QD.depends_question_id = A.question_id
left join questions Q on Q.question_id = QD.question_id
UNION
select NULL AS P_PID,
  NULL AS A_PID,
  A.question_id as A_QID,
  A.answer_val as A_VAL,
  QD.question_id as QD_QID,
  QD.depends_question_id AS QD_DQID,
  QD.depends_answer_val AS QD_VAL,
  Q.type_id AS Q_TYPE
from question_depends QD
left join answers A on QD.depends_question_id = A.question_id
left join questions Q on Q.question_id = QD.question_id
  where A.question_id IS NULL 

...但输出包含每个 paper_id 的每一行的答案数据,而不仅仅是该 paper_id 的答案数据。任何想法表示赞赏!使用这个小样本数据集上面的选择输出:

P_PID   A_PID   A_QID   A_VAL   QD_QID  QD_DQID QD_VAL  Q_TYPE
1001                            
1002    1002    1       1       2       1       1       2
1002    1002    1       1       3       1       0       1
1002    1002    4       0       NULL    NULL    NULL    NULL
1003    NULL    NULL    NULL    NULL    NULL    NULL    NULL
1004    1004    1       0       2       1       1       2
1004    1004    1       0       3       1       0       1
1004    1004    3       1       NULL    NULL    NULL    NULL
1005    1005    1       1       2       1       1       2
1005    1005    1       1       3       1       0       1
1006    NULL    NULL    NULL    NULL    NULL    NULL    NULL

理想的输出(如果我没有打错任何东西)将是:

P_PID   A_PID   A_QID   A_VAL   QD_QID  QD_DQID QD_VAL  Q_TYPE
1001    NULL    NULL    NULL    2       1       1       2
1001    NULL    NULL    NULL    3       1       0       1
1002    1002    1       1       2       1       1       2 
1002    NULL    NULL    NULL    3       1       0       1
1002    1002    4       0       NULL    NULL    NULL    3
1003    NULL    NULL    NULL    2       1       1       2
1003    NULL    NULL    NULL    3       1       0       1
1004    1004    1       0       2       1       1       2 
1004    NULL    NULL    NULL    3       1       0       1
1004    1004    3       1       NULL    NULL    NULL    1
1005    1005    1       1       2       1       1       2
1005    NULL    NULL    NULL    3       1       0       1
1006    NULL    NULL    NULL    2       1       1       2
1006    NULL    NULL    NULL    3       1       0       1

最佳答案

“分而治之”。将问题分为三种情况。

 SELECT /*Answers and no depends*/ p.paper_id AS p_pid,
  a.paper_id AS a_pid,
  a.question_id AS a_qid,
  a.answer_val AS a_val,
  qd.question_id AS qd_qid,
  qd.depends_question_id AS qd_dqid,
  qd.depends_answer_val AS qd_val,
  q.type_id AS q_type
 FROM papers p
 JOIN answers a 
    ON a.paper_id = p.paper_id
 LEFT OUTER JOIN question_depends qd 
    ON  a.question_id = qd.depends_question_id 
        AND 
        a.answer_val = qd.depends_answer_val
 LEFT OUTER JOIN questions q 
    ON q.question_id = a.question_id
 WHERE qd.question_id IS NULL
UNION
SELECT /*Answers and depends*/ p.paper_id AS p_pid,
  a.paper_id AS a_pid,
  a.question_id AS a_qid,
  a.answer_val AS a_val,
  qd.question_id AS qd_qid,
  qd.depends_question_id AS qd_dqid,
  qd.depends_answer_val AS qd_val,
  q.type_id AS q_type
 FROM papers p
 JOIN answers a 
    ON a.paper_id = p.paper_id
 LEFT OUTER JOIN question_depends qd 
    ON  a.question_id = qd.depends_question_id 
        AND 
        a.answer_val = qd.depends_answer_val
 LEFT OUTER JOIN questions q 
    ON q.question_id = qd.question_id
 WHERE qd.question_id IS NOT NULL
UNION 
SELECT /*Missing answer*/ p.paper_id AS p_pid,
  a.paper_id AS a_pid,
  a.question_id AS a_qid,
  a.answer_val AS a_val,
  qd.question_id AS qd_qid,
  qd.depends_question_id AS qd_dqid,
  qd.depends_answer_val AS qd_val,
  q.type_id AS q_type
 FROM papers p
 CROSS JOIN question_depends qd
 JOIN questions q 
    ON q.question_id = qd.question_id
 LEFT OUTER JOIN answers a 
    ON a.paper_id = p.paper_id
        AND
        a.question_id = qd.depends_question_id
        AND
        a.answer_val = qd.depends_answer_val
 WHERE a.question_id IS NULL 
 ORDER BY 1, 7 DESC;

您可以在 SQL Fiddle 上查看结果 http://sqlfiddle.com/#!9/fbd3a9/3

关于MySQL 查询根据不同条件连接 4 个表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45947127/

有关MySQL 查询根据不同条件连接 4 个表的更多相关文章

  1. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  2. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  4. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  5. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  6. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  7. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  8. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  9. sql - 查询忽略时间戳日期的时间范围 - 2

    我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

  10. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

    我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

随机推荐