【问题标题】:mySQL Left Join 5 Tables?mySQL 左连接 5 个表?
【发布时间】:2018-10-14 08:46:56
【问题描述】:

提前感谢您的帮助。我正在使用 mySQL 数据库中的 5 个表。该系统是这样的,我有一个名为“所有者”(客户)的顶级表,该表具有本地业务(商店)。这些所有者外出并在 yelp (citation_sources) 等网站上创建帐户,因此拥有登录凭据 (citation_login)。一旦他们在引文来源拥有帐户,他们就会将商店添加到目录中。

我希望创建一个查询来选择所有引文来源,无论所有者是否有帐户,并遍历记录集,同时显示他们拥有帐户的每个引文来源的登录信息与任何商店列表一样。

我的问题与在 5 个表上进行左连接有关。我遗漏了大部分字段,但设置了主键和外键连接的顺序是否重要,即。从一个特定的表开始,以另一个表结束?

我试过这个命令,但它只带回 33 行,而实际上有 96 个 citation_sources。

我想我明白了。我创建了一个名为“citation_shop”的新表,其中包含一个复合主键 - 引文 - 商店。然后我运行了一个查询,它得到了我想要的结果。我最终在第一个左连接中添加了一个条件。

SELECT citation_sources.name, citation_shop.shop from citation_sources left join citation_shop on citation_sources.id = citation_shop.citation 和 citation_shop.shop in (6,7) left join stores on citation_shop.shop = shop.id group by citation_sources.name , citation_shop.shop 限制 100

CREATE TABLE `citation_shop` (
  `shop` smallint(5) UNSIGNED NOT NULL,
  `citation` smallint(6) UNSIGNED NOT NULL,
  `url` text NOT NULL,
  `count` smallint(3) UNSIGNED NOT NULL,
  `status` tinyint(1) UNSIGNED NOT NULL,
  `sort` tinyint(3) UNSIGNED NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

--
-- Indexes for dumped tables
--

--
-- Indexes for table `citation_shop`
--
ALTER TABLE `citation_shop`
  ADD PRIMARY KEY (`citation`,`shop`);

select owners.id as owner_id, shops.id as shop_id, citation_sources.name, citation_shop_urls.url, citation_logins.password 
from owners 
inner join shops on owners.id = shops.owner_id 
left join citation_logins on owners.id = citation_logins.owner 
left join citation_sources on citation_logins.c_source = citation_sources.id 
left join citation_shop_urls on citation_sources.id = citation_shop_urls.citation_id 
where owners.id = 3 
group by citation_sources.name

这是我的表格,按我认为的相关性排序:

CREATE TABLE `owners` (
  `id` smallint(6) UNSIGNED NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

CREATE TABLE `shops` (
  `id` smallint(5) UNSIGNED NOT NULL,
  `title` varchar(50) DEFAULT '',
  `owner_id` smallint(5) UNSIGNED NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `citation_sources` (
  `id` smallint(6) UNSIGNED NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `citation_shop_urls` (
  `shop` smallint(5) UNSIGNED NOT NULL DEFAULT '0',
  `citation_id` tinyint(5) UNSIGNED NOT NULL DEFAULT '0',
  `owner` smallint(6) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


CREATE TABLE `citation_logins` (
  `c_source` smallint(5) UNSIGNED NOT NULL DEFAULT '0',
  `owner` smallint(6) NOT NULL,
  `user_name` text NOT NULL,
  `password` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

【问题讨论】:

  • StackOverflow 不是免费的编码服务。 SO希望您try to solve your own problem first。请更新您的问题以在minimal reproducible example 中显示您已经尝试过的内容。如需更多信息,请参阅How to Ask,并拨打tour :)
  • LEFT JOIN 的顺序很重要。左边的表是父表,右边的表是子表。结果将包括来自父级的行,即使它们在子级中没有匹配项。
  • 除了省略citation_shop_urls,您的查询看起来应该可以工作。你有问题吗?
  • 你为什么使用GROUP BY而不使用SUM()MAX()这样的聚合函数?
  • 你能展示一些样本数据和预期的结果吗?

标签: mysql


【解决方案1】:

LEFT JOIN 中,第一个表是您获取所有行的表,即使它们在其他表中没有匹配项。所以如果你想要所有citation_sources,即使是那些不与任何owner关联的,那么citation_sources应该是LEFT JOIN左边的表格。

要将所有者信息仅过滤到id = 3,请将o.id = 3 放在与owners 连接的ON 子句中。然后使用WHERE 子句删除所有其他行。

SELECT o.id as owner_id, s.id as shop_id, cs.name, u.url, cl.password 
FROM citation_sources AS cs
LEFT JOIN citation_shop_urls AS u ON u.citation_id = cs.id
LEFT JOIN citation_logins AS cl ON cs.id = cl.c_source
LEFT JOIN owners AS o ON o.id = cl.owner AND o.id = 3
LEFT JOIN shops AS s ON s.owner_id = o.id
WHERE o.id IS NULL OR o.id = 3

【讨论】:

  • 我非常感谢您在这方面的帮助。我运行了你的命令,它带回了 19K 行。假设我想要一个所有者,id = 3,它有 2 个商店,ids 6 和 7,我想要一个 192 行的记录集,(96 个引用来源 x 2 个商店)。当设置一个条件时,例如 whereowners.id = 3 我得到 33 行。
  • 您在问题中说您想要所有来源,即使它们没有所有者。那么所有者 ID 3 与它有什么关系呢?
  • 你的意思是你想要所有的来源,如果所有者 3 有一个帐户你想要帐户信息?
  • 我想要实现的是这个。客户(所有者)登录后端并单击引文来源。他看到了 96 个来源的列表,Yelp、CitySearch、Angie 的列表等。在每个来源下,他看到(或没有看到)列出了他的商店。
  • 取得进展,谢谢。我得到一个有 16k 行的记录集。如果我可以排除 owner = null 的行,它会起作用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-18
  • 2016-08-31
  • 2015-03-13
  • 2014-02-04
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
相关资源
最近更新 更多