나는 당신의 문제에 대한 해결책을 찾았다 고 생각하지만, 나는 그것이 당신이 원하는대로 작동하는지 확신하지 못한다. 어쨌든, 꽤 복잡합니다. 그것은 레코드를 뒤집기 위해 임시 테이블을 사용하는 저장 프로 시저입니다. 아직 극복 할 수없는 버그가 있습니다. 임시 테이블의 결과를 캐시합니다. SELECT 문에 SQL_NO_CACHE를 추가하려고 시도했지만 효과가 없습니다. 아래 절차는 여기에 잘 나타나지 않을 수도 있으므로 this GitHub gist에서도 살펴볼 수 있습니다. 그 요지는 또한 테스트 테이블의 구조와 데이터를 포함합니다. 모든 버그 보고서 또는 피드백은 크게 감사하겠습니다.
DELIMITER $$
CREATE PROCEDURE `report`()
BEGIN
DECLARE col_number INT(2) DEFAULT 0;
DECLARE counter INT(2) DEFAULT 0;
DECLARE done INT(1) DEFAULT 0;
DECLARE last_prod VARCHAR(128) DEFAULT "";
DECLARE prod_name VARCHAR(128);
DECLARE cross_prod_name VARCHAR(128);
DECLARE col_name VARCHAR(32);
DECLARE create_temp_tbl TEXT;
-- ------------------------------------------------------------------------
-- Query for fetching products and associated cross products.
-- ------------------------------------------------------------------------
DECLARE cross_products CURSOR FOR
SELECT SQL_NO_CACHE
b.product_name,
c.product_name
FROM cross_sell_products AS a
INNER JOIN product_names AS b ON
a.product_id = b.product_id
INNER JOIN product_names AS c ON
a.cross_sell_product_id = c.product_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
-- ------------------------------------------------------------------------
-- Find the largest number of cross products for a single product
-- ------------------------------------------------------------------------
SELECT SQL_NO_CACHE
COUNT(*) AS total INTO col_number
FROM cross_sell_products
GROUP BY product_id
ORDER BY total DESC
LIMIT 1;
-- ------------------------------------------------------------------------
-- Get rid of any instance of report_tmp. Given its structure is changing
-- from procedure call to procedure call, it might cause problems because
-- of the different number of columns it has versus the ones that we want
-- to insert.
-- ------------------------------------------------------------------------
DROP TABLE IF EXISTS report_temp;
-- ------------------------------------------------------------------------
-- Create a table with as many fields for cross products as the number
-- stored in col_number (which is the maximum number of cross products for
-- a single product).
-- Also, make product_name a primary key. We'll need this later in the
-- insertion phase.
-- ------------------------------------------------------------------------
SET create_temp_tbl = "CREATE TEMPORARY TABLE report_temp (product_name VARCHAR(128) PRIMARY KEY, ";
WHILE counter < col_number DO
SET col_name = CONCAT("cross_sel_product_", counter);
SET create_temp_tbl = CONCAT(create_temp_tbl, CONCAT(col_name, " VARCHAR(128)"));
IF counter != col_number - 1 THEN
SET create_temp_tbl = CONCAT(create_temp_tbl, ", ");
END IF;
SET counter = counter + 1;
END WHILE;
SET @x = CONCAT(create_temp_tbl, ");");
PREPARE stmt FROM @x;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
TRUNCATE TABLE report_temp;
-- ------------------------------------------------------------------------
-- Begin fetch of products and cross products
-- ------------------------------------------------------------------------
OPEN cross_products;
REPEAT
FETCH cross_products INTO prod_name, cross_prod_name;
IF NOT done THEN
-- ----------------------------------------------------------------
-- Be sure to reset the counter every time the product group is
-- changing, so that we don't attempt to use more fields than
-- there are in the temporary table.
-- ----------------------------------------------------------------
IF NOT prod_name = last_prod THEN
SET counter = 0;
SET last_prod = prod_name;
END IF;
-- ----------------------------------------------------------------
-- For each cross product of a product, try to insert it, in case
-- it's not the first one in the group a key duplication error will
-- be reported. In this case, update the entry with a new cross
-- product.
-- ----------------------------------------------------------------
SET col_name = CONCAT("cross_sel_product_", counter);
SET @insert_stmt = CONCAT("INSERT INTO report_temp SET"
," product_name = ?, "
, col_name ," = ? "
,"ON DUPLICATE KEY UPDATE "
, col_name ," = ?");
SET @prod_name = prod_name;
SET @cross_prod_name = cross_prod_name;
PREPARE stmt_ins FROM @insert_stmt;
EXECUTE stmt_ins USING @prod_name, @cross_prod_name, @cross_prod_name;
DEALLOCATE PREPARE stmt_ins;
-- Go to next field
SET counter = counter + 1;
END IF;
UNTIL done END REPEAT;
CLOSE cross_products;
-- ------------------------------------------------------------------------
-- Return desired result
-- ------------------------------------------------------------------------
SELECT SQL_NO_CACHE * FROM report_temp;
END $$
DELIMITER ;
물론이 - 우리가 ID 1이있을 때 내가 제대로 따른다면, –
는 쇼핑 카트, 그리고 각 제품은 ('이 품목을 구매 한 고객은 다음 항목에 관심'같은 것을) 관련 제품을 가질 수 있습니다 우리 cross_sell_products 테이블을 점검하고 product_id = id (이 경우 1)로 해당 테이블의 모든 행을 찾으십시오. 그런 다음 corss_sell_product_1 열이 첫 번째 행의 corss_sell_product_id (이 경우 2 => 내 두 번째 제품)에 해당하는 product_name을 갖기를 원합니다. 그런 다음 두 번째 행에 대해 동일한 작업을 수행합니다 (존재하는 경우). –
이 애플리케이션에서이 그룹화를 수행해야한다고 생각합니다. 어쨌든 내가 아는 한, MySQL에서 그렇게하기가 어렵습니다. –