[英]UNION loses functional dependence on GROUP BY columns
我正在嘗試實現一個使用MySQL 5.7.18-0ubuntu0.16.04.1作為其后端的產品搜索表單。 我希望用戶能夠鍵入SKU前綴,標題前綴或整個EAN或UPC條形碼,並將結果作為產品ID,SKU,標題和換行符分隔的產品條形碼列表。 但是,當我UNION
一起從查詢結果,以配合每個可能的表,其中一個產品可能會發現,不知何故失去了MySQL的軌道上的函數依賴 ,導致GROUP BY
失敗,錯誤1055。
為了簡化MCVE的問題,我刪除了按供應商SKU搜索的部分,該部分類似於按條形碼搜索的部分,以及刪除了多個采購訂單中增加數量的部分,該部分類似於添加換行符分隔的條形碼的部分。
-- ONLY_FULL_GROUP_BY is enabled by default in MySQL 5.7.5+ but
-- is disabled by default in rextester
SET SESSION SQL_MODE = 'STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY';
SHOW VARIABLES LIKE 'version';
-- These commands need to be run on a database where you have
-- privileges including CREATE TABLE.
CREATE DATABASE IF NOT EXISTS this_mcve;
USE this_mcve;
-- Now create some tables to query
DROP TABLE IF EXISTS t_products, t_barcodes;
CREATE TABLE t_products (
skuid INTEGER UNSIGNED PRIMARY KEY AUTO_INCREMENT,
sku VARCHAR(40) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL UNIQUE,
title VARCHAR(80) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
INDEX (title(10))
);
CREATE TABLE t_barcodes (
barcode VARCHAR(15) CHARACTER SET ascii COLLATE ascii_general_ci PRIMARY KEY,
skuid INTEGER UNSIGNED NOT NULL,
INDEX (skuid) -- in production this is a FOREIGN KEY
);
INSERT INTO t_products (skuid, sku, title) VALUES
(1, 'SKU1', 'title 1'),
(2, 'SKU2', 'title 2'),
(3, 'SKU3', 'title 3');
INSERT INTO t_barcodes (barcode, skuid) VALUES
('BC1FORSKU1', 1),
('BC2FORSKU1', 1),
('BC1FORSKU2', 2),
('BC2FORSKU2', 2),
('BC1FORSKU3', 3),
('BC2FORSKU3', 3);
-- WORKING: Get product ID, SKU, title, and barcodes where the SKU
-- prefix or title prefix matches. In the production code, each
-- 'SK%' or the like is a PDO placeholder.
SELECT pr.skuid, pr.sku, pr.title,
GROUP_CONCAT(bc.barcode SEPARATOR '
') AS barcodes
FROM (
(SELECT DISTINCT skuid, sku, title
FROM t_products
WHERE sku LIKE 'SK%' OR title LIKE 'SK%')
) AS pr
LEFT JOIN t_barcodes AS bc ON bc.skuid = pr.skuid
GROUP BY pr.skuid;
-- WORKING: Look up all barcodes of products where one barcode
-- matches the query string
SELECT pr.skuid, pr.sku, pr.title,
GROUP_CONCAT(bc.barcode SEPARATOR '
') AS barcodes
FROM (
(SELECT DISTINCT t_products.skuid, t_products.sku, t_products.title
FROM t_products
INNER JOIN t_barcodes ON t_products.skuid = t_barcodes.skuid
WHERE t_barcodes.barcode = 'BC1FORSKU1')
) AS pr
LEFT JOIN t_barcodes AS bc ON bc.skuid = pr.skuid
GROUP BY pr.skuid;
-- But this statement gives error 1055:
-- Expression #2 of SELECT list is not in GROUP BY clause and
-- contains nonaggregated column 'pr.sku' which is not functionally
-- dependent on columns in GROUP BY clause; this is incompatible
-- with sql_mode=only_full_group_by
SELECT pr.skuid, pr.sku, pr.title,
GROUP_CONCAT(bc.barcode SEPARATOR '
') AS barcodes
FROM (
(SELECT DISTINCT skuid, sku, title
FROM t_products
WHERE sku LIKE 'BC1FORSKU1%' OR title LIKE 'BC1FORSKU1%')
UNION
(SELECT DISTINCT t_products.skuid, t_products.sku, t_products.title
FROM t_products
INNER JOIN t_barcodes ON t_products.skuid = t_barcodes.skuid
WHERE t_barcodes.barcode = 'BC1FORSKU1')
) AS pr
LEFT JOIN t_barcodes AS bc ON bc.skuid = pr.skuid
GROUP BY pr.skuid
在此語句中, pr.sku
如何在功能上不依賴於pr.skuid
? 工作語句表明,MySQL從內部查詢的DISTINCT
skuid
推斷出sku
對skuid
的功能依賴性。 但是某種程度上這種功能上的依賴並不能在UNION
生存。
確實。 似乎UNION
隱藏了對MySql的功能依賴性。
我相信,但是你可以簡化您的查詢到這一點,避免了union
:
SELECT pr.skuid,
pr.sku,
pr.title,
GROUP_CONCAT(bc.barcode SEPARATOR '
') AS barcodes
FROM t_products pr
LEFT JOIN t_barcodes AS bc1
ON bc1.skuid = pr.skuid
AND bc1.barcode = 'BC1FORSKU1'
LEFT JOIN t_barcodes AS bc
ON bc.skuid = pr.skuid
WHERE sku LIKE 'BC1FORSKU1%' OR title LIKE 'BC1FORSKU1%' OR bc1.skuid IS NOT NULL
GROUP BY pr.skuid
我們可以重新開始嗎? 我們有這個數據集...
SELECT * FROM t_products p JOIN t_barcodes b ON b.skuid = p.skuid;
+-------+------+---------+------------+-------+
| skuid | sku | title | barcode | skuid |
+-------+------+---------+------------+-------+
| 1 | SKU1 | title 1 | BC1FORSKU1 | 1 |
| 1 | SKU1 | title 1 | BC2FORSKU1 | 1 |
| 2 | SKU2 | title 2 | BC1FORSKU2 | 2 |
| 2 | SKU2 | title 2 | BC2FORSKU2 | 2 |
| 3 | SKU3 | title 3 | BC1FORSKU3 | 3 |
| 3 | SKU3 | title 3 | BC2FORSKU3 | 3 |
+-------+------+---------+------------+-------+
...我們試圖達到什么結果?
在不贊成的合唱之前,顯然這還不是答案,而是尋求利用某些格式選項。
(當然,只有白痴才會發現這一點)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.