今天,在 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
orR
无论如何,这是我提出的查询(对于 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/