MySQL:如何根据列删除多行记录的一行

Posted

技术标签:

【中文标题】MySQL:如何根据列删除多行记录的一行【英文标题】:MySQL: How to Remove One Row of a Multi-Row Record Based on Column 【发布时间】:2015-09-11 05:56:01 【问题描述】:

如果我有两个要加入的表,我会编写最简单的查询,如下所示:

SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.id

有一些记录每个 ID 有多个行,因为它们有多个雇主,所以 t1 看起来像这样:

ID         Name         Employer
12345      Jerry        Comedy Cellar
12345      Jerry        NBC
12348      Elaine       Pendant Publishing
12346      George       Real Estate
12346      George       Yankees
12346      George       NBC
12347      Kramer       Kramerica Industries

t2 与相似的 ID 相关联,但与我希望看到的一些活动相关联——因此是上面的SELECT *。虽然如果Employer 列是“NBC”,我不希望返回多行——但其他一切都很好。

这里唯一重要的另一件事是t2 小于t1,因为t1 是每个人,t2 仅来自从事特定活动的人——所以有些比赛不会从t2返回任何东西,但我仍然希望它们被返回,因此LEFT JOIN

如果我这样写查询:

SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE Employer <> "NBC"

然后它会完全删除 Jerry 和 George —— 而我真正想要的只是不返回 NBC 行,而是返回与它们关联的任何其他行。

如何在将 t1t2 连接时编写查询以返回除 NBC 之外的每一行?理想的输出将是来自t1 的所有行,无论它们是否与t2 的所有行匹配,除非在返回文件中删除所有以“NBC”为雇主的行。基本上,这里的理想是在适合的地方返回 JOIN,但无论如何删除以“NBC”为雇主的任何人的整行而不删除他们的其他行。

我写得越多,似乎我应该在JOIN 之前运行一个查询,以删除t1 中所有以“NBC”为雇主的行,然后运行正常查询。

【问题讨论】:

那么您希望这个查询做什么输出? @Mureinik 很抱歉没有包括在内 - 理想的输出将是来自 t1 的所有行,无论它们是否与所有 t2 匹配,除了删除所有带有“NBC”的行"作为返回文件中的雇主。 Ryan, “我写的越多,似乎我应该在我的 JOIN 之前运行一个查询,以删除 t1 中所有以“NBC”为雇主的行然后运行正常查询。” - NO!! :-)) mysql 能够在两个条件下使用SELECT 应用任何可应用于数据集的逻辑:1. 您的数据格式正确 2. 您的要求很明确。我认为您已经接近可行的解决方案,现在不要放弃! @DanFromGermany 谢谢!好的,我不会! 【参考方案1】:

基本子集过滤

您可以通过扩展 ON 子句来过滤两个合并(连接)子集中的任何一个。

SELECT    *
FROM      t1
LEFT JOIN t2
       ON t1.ID = t2.ID
      AND t2.Employer != 'NBC'

如果你现在得到null 值,但你不想要它们,你会添加:

WHERE t2.Employer IS NOT NULL

扩展逻辑:

SELECT    *
FROM      t1
LEFT JOIN t2
       ON (t1.ID = t2.ID AND t2.Employer != 'NBC')
       OR (t2.ID = t2.ID AND t2.Employer IS NULL)

使用UNION

基本上,JOIN 用于水平链接,UNION 用于数据集的垂直链接。

它合并到结果集:第一个没有 NBC,第二个(基本上是 OUTER JOIN)添加了 t1 中不属于 t2 的每个人。

SELECT    *
FROM      t1
LEFT JOIN t2
       ON t1.ID = t2.ID
      AND t2.Employer != 'NBC'
UNION
SELECT    *
FROM      t1
LEFT JOIN t2
       ON t1.ID = t2.ID
      AND t2.Employer IS NULL

结果集中的字符串操作

如果您只想将NBC 作为字符串删除,这里有一个解决方法:

SELECT
    t1.*,
    IF (t2.Employer = 'NBC', NULL, t2.Employer) AS Employer
FROM t1
LEFT JOIN t2
    ON t1.id = t2.id

这基本上将"NBC" 替换为NULL

【讨论】:

谢谢!这非常简单,基本上是我正在寻找的。我唯一没有预料到的是,如果我在t1 而不是t2 中有人,例如,使LEFT JOIN 不添加来自t2 的任何东西(这是我的目的所需要的),它不会'似乎不会删除以“NBC”为雇主的人,因为他们不属于JOIN。有什么我可以做的补充吗? 我不完全理解您的要求,最好在问题中提供示例输出。 谢谢——我添加了一个理想的口头输出,但如果它仍然太模糊,我可以更具体。基本上,只要t1t2 有一个匹配的键,你的似乎就很好用。但是t1 中的某些人不在t2 中(这就是我使用LEFT JOIN 的原因),但是您对LEFT JOIN 语句的添加对于ID 匹配但似乎不匹配的人来说效果很好如果该人的t2 中没有匹配的 ID,则工作。 @Ryan 我又添加了 3 个解决方案。您可以通过更多逻辑来扩展该子句。 基本上理想的情况是在适合的地方返回 JOIN,但无论如何删除以“NBC”为雇主的任何人的整行而不删除其他行。

以上是关于MySQL:如何根据列删除多行记录的一行的主要内容,如果未能解决你的问题,请参考以下文章

sql一行拆分多行记录

sqlplus多行代码怎么

哪个更快:多行还是多列?

mysql 行变列(多行变成一行/多行合并成一行/多行合并成多列/合并行)

根据列值将一行分解/拆分为多行

sql如何把行拆分为几行