0

我正在尝试实现一个使用 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 正确地从内部查询的 -ness推断出skuon的功能依赖。但不知何故,这种功能依赖在.skuidDISTINCTUNION

4

2 回答 2

0

的确。它似乎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
于 2017-07-11T19:14:30.923 回答
0

我们可以重新开始吗?我们有这个数据集...

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 |
+-------+------+---------+------------+-------+

...我们要达到什么结果集?

在不赞成的合唱之前,显然这不是(还)一个答案,而是试图利用某些格式选项。

(当然,只有白痴才会看不出来)

于 2017-07-11T21:04:54.793 回答