【问题标题】:sql how to combine three queries from two tables into one querysql如何将两个表中的三个查询合并为一个查询
【发布时间】:2016-12-22 08:36:00
【问题描述】:

我有以下两张表:

表 1

id  name
---------
A3  B2
A3  B400
A5  B100
A7  B200
A8  B6
A8  B2
A8  B3

Table2

id  name    company
-------------------
A1          company1
A2          company2
A3  B1      company3
A4          company4
A5  B2      company5
A6          company6
A7  B3      company7
A8  B4      company8
A9          company9
A10 B6      company10

我正在启动三个查询来获得我想要的,但是有三个查询。我的问题是如何在一个查询中以更有效的方式完成所有这些操作?

查询 1:

SELECT DISTINCT t1.id as ID,
        t2.company as Company,
        'FOUND' AS status
 FROM   table1 t1
        JOIN table2 t2
          ON t1.id = t2.id
group by ID

查询 1 个结果:

ID  Company     Status
-----------------------
A3  company3    FOUND
A5  company5    FOUND
A7  company7    FOUND
A8  company8    FOUND

查询 2:

SELECT DISTINCT t2.id as ID,
        t2.company as Company,
        'FOUND' AS status
 FROM   table1 t1
        JOIN table2 t2
          ON t1.name = t2.name
group by ID

查询 2 结果:

ID  Company     Status
-----------------------
A5  company5    FOUND
A10 company10   FOUND
A7  company7    FOUND

查询 3:

SELECT t1.name as ID,
        t1.name as Company,
        'NOT FOUND' AS status
 FROM   table1 t1
  WHERE  t1.name NOT IN (SELECT t2.name
                                FROM   table2 t2)
GROUP BY ID

查询 3 结果:

ID  Company     Status
-----------------------
B400    B400    NOT FOUND
B100    B100    NOT FOUND
B200    B200    NOT FOUND

最终结果输出如下:

ID      Company     Status
---------------------------
A3      company3    FOUND   
A5      company5    FOUND   
A7      company7    FOUND   
A8      company8    FOUND   
A10     company10   FOUND   
B100    B100        NOT FOUND
B200    B200        NOT FOUND
B400    B400        NOT FOUND

注意:A5A7 出现在第一个查询结果和第二个查询结果中!所以我们只需要保留一个。

如果需要一些解释: 我们从 table1 中获取唯一的ids 列表,并从 table2 中获取它们对应的 company。我们对 table1 的第二列进行类似的查询:我们从 table1 的第二列中查找第二列的值,即name,在 的第二列中查找>table2,如果我们找到它,那么我们会从 table2 中得到对应的 idcompany,但如果 id 在我们之前的查询中已经存在,那么我们放弃它,无需重复它。第三,如果我们在 table2name 中没有找到 table1name 的值,那么我们就没有对应的id也不是company,因此我们将name 的值同时归为idcompany。一般来说,如果我们在 table2table1 中找到 ids 和 names,那么我们给它们状态 FOUND 如果没有,那么 @987654348 @。

提前致谢

顺便说一下,我用union试了两次,但是查询时间长,效率不高。

【问题讨论】:

  • 你的意思是只有标题应该是大写字母吗?还是别的什么?
  • @GiorgosBetsos 确切地说,因为我们找不到任何对应的 ID 或公司,所以我们将该名称归于该名称,即 B100 既作为 ID 又作为公司。

标签: mysql sql


【解决方案1】:

这些要求令人困惑,可能值得重新评估您的数据模型。我认为UNION 解决方案是您最好的选择,可能修改为使用UNION ALL 以提高效率。

我确实整理了一个基于互斥锁的 hack,它可能与此页面上的任何其他查询一样存在许多微妙的问题。

select
  coalesce(t2.id, t1.name) AS ID,
  coalesce(t2.company, t1.name) AS Company,
  if(isnull(t2.id), 'NOT FOUND', 'FOUND') as Status
from (select 0 as mutex union select 1) as m
left join table1 as t1 on 1 = 1
left join table2 as t2 on t1.name = t2.name or (t1.id = t2.id and mutex)
group by coalesce(t2.id, t1.name)

也就是说,请仔细测试这些查询并查看您的数据和结果。根据您的输入数据,有很大的错误空间。

【讨论】:

  • 您的查询比 Giorgos 的回答要快。所以我接受它作为答案。谢谢
【解决方案2】:

尝试使用 UNION DISTINCT,例如:

SELECT DISTINCT t1.id as ID,
        t2.company as Company,
        'FOUND' AS status
 FROM   table1 t1
        JOIN table2 t2
          ON t1.id = t2.id
group by ID

union distinct

SELECT DISTINCT t2.id as ID,
        t2.company as Company,
        'FOUND' AS status
 FROM   table1 t1
        JOIN table2 t2
          ON t1.name = t2.name
group by ID

union distinct

SELECT t1.name as ID,
        t1.name as Company,
        'NOT FOUND' AS status
 FROM   table1 t1
  WHERE  t1.name NOT IN (SELECT t2.name
                                FROM   table2 t2)
GROUP BY ID

【讨论】:

  • 我知道这可以用union 完成,但它根本没有效率。这需要很多时间。
  • FWIW, UNION ALL 可能比 UNION 更有效,因为它跳过了消除重复。但这不是我个人会使用的方法。你也可以看看我建议的答案。
  • UNION ALL 效率更高,但不会消除重复项
【解决方案3】:

您的查询有一些不清楚的地方,因为它们不应该像您展示的那样执行(由于select 包含不在group by 中的非聚合)。但根据你对你正在尝试做的事情的解释......

您可以使用外连接,然后使用案例逻辑和/或合并来确定在每种情况下使用哪个值。

SELECT DISTINCT
       coalesce(t2_id.id, t2_name.id, t1.name) as ID
     , coalesce(t2_id.company, t2_name.company, t1.name) as Conpany
     , case when t2_id.id is not null or t2_name.name is not null
            then 'FOUND'
            else 'NOT FOUND'
       end status
  FROM           table1 t1
       LEFT JOIN table2 t2_id
              ON t1.id = t2_id.id
       LEFT JOIN table2 t2_name
              ON t1.name = t2_name.name

请注意,我使用DISTINCT 来确保完全相同的行不会出现多次;但这可能会根据数据返回 ID 的多行(具有不同的公司值)。我不太清楚这是什么意思,因为在问题中发布的三个查询中 DISTINCTGROUP BY 的使用对我来说似乎没有加起来。

【讨论】:

  • 好的,让我试试你的答案,然后看看 group by 的用途。
  • 其实我没有把那些分组按s,我只得到一个结果!如果我包含它们,我会得到该查询的所有结果。
  • 实际上使用合并和案例逻辑的想法很好,但它返回了很多重复项。我们想要独特的价值。
  • 再次,我不确定重复数据删除规则对我来说是否清楚,但如果您能澄清它们,我可以改进查询。最简单的事情 - 如果骗子在所有字段中都相同,那么只需说 SELECT DISTINCT 而不是 SELECT,就像在原始查询中一样。
  • 为了使GROUP BY 的行为与您在之前的评论中描述的一样,您正在运行的查询与您发布的查询必须有所不同。也许您在第二列上使用了聚合函数(如 MIN 或 MAX)?这将是另一种重复数据删除策略,可确保每个 ID 只显示一次(并且只选择其中一个名称)...
【解决方案4】:

我认为您可以使用如下查询:

SELECT DISTINCT IF(name2 IS NULL, name, ID) AS ID,
       IF(name2 IS NULL, name, Company) AS Company,
       IF(name2 IS NULL, 'NOT FOUND', 'FOUND') AS Status
FROM (       
   SELECT DISTINCT 
          CASE 
             WHEN t1.id = t2.id THEN t1.id 
             WHEN t1.name = t2.name THEN t2.id
             ELSE t1.id
          END AS ID, 
          CASE 
             WHEN t1.id = t2.id THEN t2.company
             WHEN t1.name = t2.name THEN t2.company
             ELSE t1.name
          END AS Company,
          t1.name,
          (SELECT Table2.name
           FROM Table2
           WHERE Table2.name = t1.name LIMIT 1) AS name2
   FROM Table1 AS t1
   LEFT JOIN Table2 AS t2 ON (t1.id = t2.id) OR (t1.name = t2.name)) AS t
ORDER BY ID;

查询使用单个LEFT JOIN 操作加上一个相关子查询。

Demo here

【讨论】:

  • 在某些情况下,您似乎必须再次加入 Table1 才能同时获得 FOUND 和 NOT FOUND。例如,如果您将 Table2 的“B3”单元格设为 NULL,则最终结果中将缺少 ID“A7”。
  • 这太棒了!谢谢。是否可以将每个的计数添加到另一列? i.imgur.com/DLXmBM3.png 这就是它想要的。计算 ID 在 column1-table1 中重复的次数并将其添加到该计数中,“name”(在 column1 中具有其对应 ID)重复的次数,如果它没有对应的 ID,则它自己计算它在 table1 的第二列中重复的次数。
  • @marcel 好吧,这是一个不同的问题。尝试为此要求写一篇单独的帖子。
  • @ebyrob 仔细一看,你的说法是不正确的。如果您提到 OP 中引用的三个查询中的任何一个都不会返回 table1Id=A7 的记录。
  • 我在这里发布了新问题:stackoverflow.com/questions/41260507/…
猜你喜欢
  • 2022-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多