单选连接 3 个具有 2 个不同 FK 的相关表

发布于 2024-12-11 23:54:22 字数 1080 浏览 0 评论 0原文

我有 3 个表,其中 2 个通过外键与第三个表相关。我想运行这样的查询:

SELECT * 
FROM template AS t 
LEFT JOIN web_page_content AS wpc ON wpc.template_id = t.id

...并且仍然能够获取标头和模板中的通用 id。

CREATE TABLE template 
(
  id INT AUTO_INCREMENT NOT NULL, 
  uri VARCHAR(50) NOT NULL,    
  UNIQUE INDEX template_idx (uri), PRIMARY KEY(id)
) ENGINE = InnoDB;

CREATE TABLE web_page_content 
(
  id INT AUTO_INCREMENT NOT NULL, 
  template_id INT NOT NULL, 
  content VARCHAR(50) NOT NULL, 
  PRIMARY KEY(id)
) ENGINE = InnoDB;

CREATE TABLE header 
(
  id INT AUTO_INCREMENT NOT NULL, 
  template_id INT NOT NULL, 
  content VARCHAR(50) NOT NULL, 
  PRIMARY KEY(id)
) ENGINE = InnoDB;

ALTER TABLE web_page_content 
ADD CONSTRAINT FK_95E4B6E5627579FF FOREIGN KEY (template_id) 
    REFERENCES template(id) ON DELETE CASCADE;

ALTER TABLE header 
ADD CONSTRAINT FK_95E3B5E5627579FF FOREIGN KEY (template_id) 
    REFERENCES template(id) ON DELETE CASCADE;  

INSERT INTO `template` (`id`, `uri`) VALUES (NULL, 'my_dir/my_file_0'), (NULL, 'my_dir/my_file_1');

I have 3 tables where 2 of them are related to the third one through a foreign key. I would like to run a query like:

SELECT * 
FROM template AS t 
LEFT JOIN web_page_content AS wpc ON wpc.template_id = t.id

...and still be able to get the common id's in header and template.

CREATE TABLE template 
(
  id INT AUTO_INCREMENT NOT NULL, 
  uri VARCHAR(50) NOT NULL,    
  UNIQUE INDEX template_idx (uri), PRIMARY KEY(id)
) ENGINE = InnoDB;

CREATE TABLE web_page_content 
(
  id INT AUTO_INCREMENT NOT NULL, 
  template_id INT NOT NULL, 
  content VARCHAR(50) NOT NULL, 
  PRIMARY KEY(id)
) ENGINE = InnoDB;

CREATE TABLE header 
(
  id INT AUTO_INCREMENT NOT NULL, 
  template_id INT NOT NULL, 
  content VARCHAR(50) NOT NULL, 
  PRIMARY KEY(id)
) ENGINE = InnoDB;

ALTER TABLE web_page_content 
ADD CONSTRAINT FK_95E4B6E5627579FF FOREIGN KEY (template_id) 
    REFERENCES template(id) ON DELETE CASCADE;

ALTER TABLE header 
ADD CONSTRAINT FK_95E3B5E5627579FF FOREIGN KEY (template_id) 
    REFERENCES template(id) ON DELETE CASCADE;  

INSERT INTO `template` (`id`, `uri`) VALUES (NULL, 'my_dir/my_file_0'), (NULL, 'my_dir/my_file_1');

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

彼岸花似海 2024-12-18 23:54:22

这是您要找的吗?

select 
      t.ID,
      t.uri,
      h.ID as HeaderID,
      h.Content as HeaderContent,
      wpc.id as WebPageID,
      wpc.Content as WebContent
   from
      template t
         left join header h
            on t.id = h.template_id
         left join web_page_content wpc
            on t.id = wpc.template_id

-- 编辑 --

澄清子选择与每个评论/反馈的加入。

在这种情况下,您可以通过模板 ID 以 1:1 的比例从一个表直接连接到另一个表。引擎直接在索引上找到匹配项,然后提取数据。它几乎就像引擎隐式地为您在密钥 ID 上执行 (select / from / where ) 一样。我不明白它是如何做到的,但它只是做得很好。通过执行子选择,您将强制引擎针对每个 ID 的模板表中的每条记录显式运行查询...假设您有 20 个模板和 1000 个网页内容页面。通过执行子选择(例如 where EXISTS),实际上每个匹配的 ID 都会显式运行 select/from 查询 1000 次。

对于笛卡尔,如果您只列出没有连接条件的“From”表,您将得到一个结果集,其数量与表“A”中的记录数乘以表“B”中的记录数。因此,如果您执行了简单,

select
     t.*,
     wpc.*
   from
      template t,
      web_page_content wpc
   order by...

没有 WHERE(连接它们)或显式 JOIN,并且上面的记录计数示例...您最终会在结果集中得到 20,000 条记录。

Is this what you are looking for?

select 
      t.ID,
      t.uri,
      h.ID as HeaderID,
      h.Content as HeaderContent,
      wpc.id as WebPageID,
      wpc.Content as WebContent
   from
      template t
         left join header h
            on t.id = h.template_id
         left join web_page_content wpc
            on t.id = wpc.template_id

-- EDIT --

To clarify sub-selects vs join per comment/feedback.

In this case, you have the capacity to do a direct join from one table to another in a 1:1 ratio by the template ID. The engine finds matches directly on the indexes to then pull the data. Its almost like the engine is implicitly doing a (select / from / where ) on the key ID for you. I don't understand the whole under-the-hood of HOW it does it, it just does it well. By doing a sub-select, you are forcing the engine to explicitly run the query for every record in template table per ID... Say you have 20 templates, and 1000 web content pages. By doing a sub-select (such as where EXISTS) would in effect run the select/from query 1000 times explicitly per ID matched.

With respect to a Cartesian, if you just listed the "From" tables without a join condition, you get a result set that is as many records form table "A" TIMES as many in table "B".. so if you did a simple

select
     t.*,
     wpc.*
   from
      template t,
      web_page_content wpc
   order by...

WITHOUT a WHERE (joining them), or explicit JOIN, and the above record counts sample... you would end up with 20,000 records in the result set.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文