【问题标题】:MySQL use one subquery more timesMySQL 多次使用一个子查询
【发布时间】:2013-05-05 08:06:55
【问题描述】:

我只是 SQL 的初学者,所以请不要担心 :)

我有存储字典单词翻译的表。该表有列idla(语言)、lb(目标语言)、wa(原始词)、wb(翻译词)和一些更无关紧要的列:)。我想显示一个表格概述,其中将是所有语言的列表,其中包含每种语言中的字数加上 SUM 作为总字数的语言的行(所有仅不同单词的计数)。

我写了这个查询:

SELECT `lng`, COUNT(`word`) AS `count` 
FROM (
  SELECT DISTINCT * 
  FROM (
     SELECT DISTINCT `la` AS `lng`, `wa` AS `word` 
     FROM `dict_trans` 
     UNION ALL 
     SELECT DISTINCT `lb` AS `lng`, `wb` AS `word` 
     FROM `dict_trans`
  ) AS `tbla`
) AS `tblb` GROUP BY `lng`
UNION ALL
SELECT 'sum' AS `lng`, COUNT(`word`) AS `count` 
FROM (
  SELECT DISTINCT * 
  FROM (
    SELECT DISTINCT `la` AS `lng`, `wa` AS `word` 
    FROM `dict_trans` 
    UNION ALL 
    SELECT DISTINCT `lb` AS `lng`, `wb` AS `word` 
    FROM `dict_trans`
  ) AS `tblc`
) AS `tbld` ORDER BY `count` DESC

但我认为多次执行一个子查询非常愚蠢且性能不友好。

SELECT DISTINCT * 
FROM (
  SELECT DISTINCT `la` AS `lng`, `wa` AS `word` 
  FROM `dict_trans` 
  UNION ALL 
  SELECT DISTINCT `lb` AS `lng`, `wb` AS `word` 
  FROM `dict_trans`
) AS `tbla`

我尝试在代码的第二部分从第一部分传递对表的引用:

SELECT `lng`, COUNT(`word`) AS `count` 
FROM (
  SELECT DISTINCT * 
  FROM (
     SELECT DISTINCT `la` AS `lng`, `wa` AS `word` 
     FROM `dict_trans` 
     UNION ALL 
     SELECT DISTINCT `lb` AS `lng`, `wb` AS `word` 
     FROM `dict_trans`
   ) AS `tbla`
) AS `tblb` GROUP BY `lng`
UNION ALL
SELECT 'sum' AS `lng`, COUNT(`word`) AS `count` 
FROM `tblb` 
ORDER BY `count` DESC

但是抛出了错误(#1146 - 表 'db.tblb' 不存在)。

不创建临时表可以解决这个问题吗?

【问题讨论】:

  • @a_horse_with_no_name 通常可以,但可以这样做with rollup
  • @Strawberry id 是标准行标识符

标签: mysql sql database subquery


【解决方案1】:

您不需要查询的所有复杂性。 UNION 表示 UNION DISTINCT,因此不需要 3 级嵌套,可以使用 WITH ROLLUP 修饰符完成额外的计数:

SELECT lng AS language, 
       COUNT(word) AS WordCount 
FROM
  ( SELECT la AS lng, wa AS word 
    FROM dict_trans 
  UNION                                 -- DISTINCT is the default
    SELECT lb, wb 
    FROM dict_trans
  ) AS t
GROUP BY lng
  WITH ROLLUP ;

如果你想排序,你需要另一个嵌套:

SELECT language, WordCount 
FROM
  ( SELECT COALESCE(lng, 'Total') AS language, 
           COUNT(word) AS WordCount 
    FROM
      ( SELECT la AS lng, wa AS word 
        FROM dict_trans 
      UNION                                 -- DISTINCT is the default
        SELECT lb, wb 
        FROM dict_trans
      ) AS t
    GROUP BY lng
      WITH ROLLUP 
  ) AS tmp
ORDER BY CASE WHEN language = 'Total' THEN 1 ELSE 0 END,
         WordCount DESC ;

这个查询最昂贵的部分将是UNION(因为您需要DISTINCT)和GROUP BY 操作。如果您想要效率,最好有一个包含所有不同语言和单词组合的单独表,然后在该表上分组(不需要联合)。 dict_trans 将是一个“联结”表,您将有 2 个外键,指向该新的不同语言单词表。

【讨论】:

  • 但是语句ROLLUPORDER BY是互斥的,所以我必须使用你的代码嵌套到另一个SELECT,这里将使用ORDER BY
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多