簡體   English   中英

UNION失去對GROUP BY列的功能依賴性

[英]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推斷出skuskuid的功能依賴性。 但是某種程度上這種功能上的依賴並不能在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM