MySQL GROUP BY 内的子查询由一两列和一个 WHERE 子句组成,它的解释是什么?

标签 mysql sql group-by

今天,在 SQL 暂停一段时间后,我遇到了以下查询:

There's an orders table:

CREATE TABLE `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_type` char(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'C',
  `order_number` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `postal_code` char(5) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Each order has:

  • 独特的id ;
  • order_type可以是 C , S , R , RS , RR , RC (它们的意思并不重要,它们是 仅由系统内部使用);
  • 一个order_number这是一个代码 代表与订单绑定(bind)的账单(请注意,一个或 更多订单可能会绑定(bind)同一个bill_number , 我知道一个 INT 列会更好,但我不是创建此表的人);
  • 和一个postal_code这是我的邮政编码的 5 个字符代码 国家(与 bill_number 相同,INT 列会更好,我 知道)。

Further, I have a postal_codes table:

CREATE TABLE `postal_codes` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `postal_code` char(5) COLLATE utf8_unicode_ci NOT NULL,     
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

现在,我需要做的是:

Given a 5 char postal code, find its id together with the count of the bills bound to the orders which are of type S, C or R

无论如何,这是我提出的查询(对于 postal_code -> 48890 ):

SELECT b.id, COUNT(*) count
FROM (
   SELECT c.id, c.postal_code
   FROM (
      SELECT o.`postal_code` FROM `orders` o
      WHERE o.`order_type` IN ('S', 'C', 'R')
      AND o.`postal_code` IS NOT NULL AND o.`postal_code` NOT LIKE ''
      GROUP BY o.`order_number`, o.`postal_code`
   ) a
   JOIN `postal_codes` c
       ON a.`postal_code` = c.`postal_code`
   WHERE c.`postal_code` = "48890"
) b
GROUP BY b.id

这是一个 fiddle :http://sqlfiddle.com/#!9/3dee8/4

现在,它的工作原理与预期一致,唯一需要注意的是最里面的GROUP BY :我必须按 o 分组。 order_number首先是 o.postal_code因为我在编写上面的查询之前编写了以下查询:

SELECT b.id, COUNT(*) count
    FROM (
       SELECT c.id, c.postal_code
       FROM (
          SELECT o.`postal_code` FROM `orders` o
          WHERE o.`order_type` IN ('S', 'C', 'R')
          AND o.`postal_code` IS NOT NULL AND o.`postal_code` NOT LIKE ''
          GROUP BY o.`order_number`
       ) a
       JOIN `postal_codes` c
           ON a.`postal_code` = c.`postal_code`
       WHERE c.`postal_code` = "48890"
    ) b
    GROUP BY b.id

有时没有按预期工作(我说 sometimes 因为现在它似乎可以与我在 fiddle 中写的花哨 Schema 一起工作,但有时会出现错误的 COUNT(*) 而不是由返回的 COUNT(*)返回了上面的查询)

有人可以告诉我这两个查询之间有什么区别吗(第一个查询在最里面的子查询中有两个 GROUP BY 列,这似乎总是对我有用,第二个查询只有一个 GROUP_BY 列,有时有效(在这种情况下,如果我会找出原因,我会更新这个问题)有时不会并返回错误的 COUNT(*) )?为什么在 GROUP BY 中使用两列始终可以确保正确的最终 COUNT(*)返回,而使用一列则不会返回?

我有点困惑。

感谢您的关注。

更新:我发布的 Fiddle 似乎不起作用,无论如何,这里是我使用的示例模式的 SQL 代码:

-- SQL Fiddle Build Schema
    CREATE TABLE `orders` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `order_type` char(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'C',
      `order_number` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
      `postal_code` char(5) COLLATE utf8_unicode_ci DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `postal_codes` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `postal_code` char(5) COLLATE utf8_unicode_ci NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO orders (order_type, order_number, postal_code) VALUES ("S", "192010NJDOS", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("C", "192010NJDOS", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("R", "192010NJDOS", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("S", "129019302KS", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("C", "129019302KS", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("C", "4444HHJSKAA", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("C", "4444HHJSKAA", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("S", "4444HHJSKAA", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("S", "4444HHJSKAA", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("S", "11111AAAAAA", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("C", "BBBBB222222", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("R", "FFFFFFFK933", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("RC", "777777SSSSS", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("RS", "777877SSSSS", "48890");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("RR", "779977SSSSS", "48890");

INSERT INTO orders (order_type, order_number, postal_code) VALUES ("S", "88818999999", "65889");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("C", "88818999999", "65889");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("R", "88818999999", "65889");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("S", "7777JJJJJJJ", "65889");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("C", "AJSJ8888LLL", "65889");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("RC", "AJSJ888899L", "65889");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("RC", "AJSJ888899L", "65889");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("RS", "AJSJ888899L", "65889");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("RR", "AJS7788899L", "65889");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("RR", "AMMMM88899L", "65889");

INSERT INTO orders (order_type, order_number, postal_code) VALUES ("S", "00001020202", "12033");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("C", "00001020202", "12033");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("R", "KKKKKKKKSK2", "12033");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("S", "KKKKKKKKSK2", "12033");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("C", "KKKKKKKKSK2", "12033");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("RC", "DKSKOKDOKOK", "12033");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("RS", "KKKKKKKKSK2", "12033");
INSERT INTO orders (order_type, order_number, postal_code) VALUES ("RR", "KKKKKK99999", "12033");
-- ---
INSERT INTO postal_codes (postal_code) VALUES ("48890");
INSERT INTO postal_codes (postal_code) VALUES ("65889");
INSERT INTO postal_codes (postal_code) VALUES ("12033");

-- SQL Fiddle 
 SELECT b.id, COUNT(*) count
        FROM (
           SELECT c.id, c.postal_code
           FROM (
              SELECT o.`postal_code` FROM `orders` o
              WHERE o.`order_type` IN ('S', 'C', 'R')
              AND o.`postal_code` IS NOT NULL AND o.`postal_code` NOT LIKE ''
              GROUP BY o.`order_number`
           ) a
           JOIN `postal_codes` c
               ON a.`postal_code` = c.`postal_code`
           WHERE c.`postal_code` = "48890"
        ) b
        GROUP BY b.id

最佳答案

您的查询似乎太复杂了。这是一种表达方式:

  SELECT p.postal_code, p.id, count(*)
  FROM `orders` o JOIN
       postalcodes p
       ON o.postal_code = p.postal_code
  WHERE o.`order_type` IN ('S', 'C', 'R') AND
        p.postal_code = $Postal_Code
  GROUP BY p.postal_code, p.id;

请注意,严格来说,GROUP BY 是不必要的,但如果您想要多个邮政编码的值,它会很有用。

另外一点,数据结构有点困惑。 Orders 中的邮政编码应该是主键 id 而不是邮政编码。

编辑:

要获得零计数,您可以执行以下操作:

  SELECT p.postal_code, p.id, count(o.postal_code)
  FROM postalcodes p left join
       orders o
       ON o.postal_code = p.postal_code and
          o.order_type IN ('S', 'C', 'R')
  WHERE p.postal_code = $Postal_Code
  GROUP BY p.postal_code, p.id;

关于MySQL GROUP BY 内的子查询由一两列和一个 WHERE 子句组成,它的解释是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33553917/

相关文章:

php - 制作 'wish list' 功能的最佳方法

sql - 能够获取 BigQuery 中每个数组条目的 "index"(或序数值)吗?

r - 如何通过对 R 中的条目进行分组来创建时间序列?

检索每个分组 ID 的中值的 MySQL 中值查询

php mysql fetch语句获取问题

mysql - 按查询顺序发出

mysql - 从对象数组中选择某些键

多列上的MySQL外键?

sql - 计算列分组依据

sql - 无法理解使用 where 和 group by 的子查询代码