I'm trying to find orders with only one item in a database running on MySQL 5.7.23 on Ubuntu 18.04 LTS. But somehow MySQL can't infer that COUNT(*) = 1
implies a functional dependence.
The following 2-table database of orders with order items illustrates the failure:
DROP TABLE IF EXISTS t_o, t_oi;
CREATE TABLE t_o (
order_id INTEGER UNSIGNED PRIMARY KEY,
placed_on DATE NOT NULL,
INDEX (placed_on)
);
INSERT INTO t_o (order_id, placed_on) VALUES
(1, '2018-10-01'),
(2, '2018-10-02');
CREATE TABLE t_oi (
item_id INTEGER UNSIGNED PRIMARY KEY AUTO_INCREMENT,
order_id INTEGER UNSIGNED NOT NULL,
sku VARCHAR(31) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
qty INTEGER UNSIGNED NOT NULL,
unit_price INTEGER UNSIGNED NOT NULL,
INDEX (sku),
FOREIGN KEY (order_id) REFERENCES t_o (order_id)
ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO t_oi (order_id, sku, qty, unit_price) VALUES
(1, 'SO', 1, 599),
(1, 'SF', 2, 399),
(2, 'SU', 1, 399);
SELECT t_oi.order_id, t_o.placed_on, t_oi.sku, t_oi.qty, t_oi.unit_price
FROM t_o
INNER JOIN t_oi ON t_o.order_id = t_oi.order_id
GROUP BY t_oi.order_id
HAVING COUNT(*) = 1
I expect this to return (2, '2018-10-02', 'SU', 1, 399)
because it is the only order with only one item. I don't want any rows where order_id = 1
because that order has more than one item. But instead, MySQL gives the following error:
#1055 - Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'phs_apps.t_oi.sku' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
The manual explains "functionally dependent". But is there a way to express this functional dependence to MySQL that's cleaner than slinging MIN()
around each output column for which MySQL complains? If at all possible, I'd prefer a solution that does not involve joining to t_oi
twice, once to find relevant t_o.order_id
values and once to append the details of each such order's sole item, as including a table twice in a single query is incompatible with use of TEMPORARY TABLE
because of a 13-year-old "Can't reopen table" bug.