블로그를 이전 중이라 완료되기 전까지는 벨로그에 작성할 계획입니다.
이후 모든 글은 https://weekwith.me 에 작성 예정이니 다른 글이 궁금하시다면 해당 링크를 통해 방문해주세요.본 글은 [ LeetCode ] 2253. Dynamic Unpivoting of a Table를 풀고 작성한 글입니다.
Table: Products
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| product_id | int |
| store_name1 | int |
| store_name2 | int |
| : | int |
| : | int |
| : | int |
| store_namen | int |
+-------------+---------+
product_id is the primary key for this table.
Each row in this table indicates the product's price in n different stores.
If the product is not available in a store, the price will be null in that store's column.
The names of the stores may change from one testcase to another. There will be at least 1 store and at most 30 stores.
Implement the procedure UnpivotProducts
to reorganize the Products
table so that each row has the id of one product, the name of a store where it is sold, and its price in that store. If a product is not available in a store, do not include a row with that product_id
and store
combination in the result table. There should be three columns: product_id
, store
, and price
.
The procedure should return the table after reorganizing it.
Return the result table in any order.
[ 알고리즘 ] LeetCode 2252. Dynamic Pivoting of a Table 글에서 풀이한 것을 참고로 해결했다.
GROUP_CONCAT
함수를 활용해 똑같이 구문을 문자열로 만들어주는데 이때 컬럼명을 가져와야 하기 때문에 information_schema
스키마 테이블을 활용했다.
product_id
필드는 별도로 건들여 줄 필요 없고 단순히 기존 Products
테이블에서 컬럼명이 곧 price
필드의 값이 되기 때문에 price
필드에 대한 부분은 컬럼명을 그대로 사용하고 store
필드의 경우 해당 컬럼명, 다시 말해 상점명이 문자열로 존재해야 하기 때문에 따옴표(" "
) 를 활용해서 문자열로 만들어준다
추가적으로 값이 NULL
인 경우를 무시하기 위해 CONCAT
함수 내부에 WHERE
구의 조건을 활용하며 이때 해당 구를 통해 얻게 된 결괏값을 수평으로 결합해주기 위해서 GROUP_CONCAT
함수는 SEPARATOR
키워드를 활용하여 UNION
키워드를 구분점으로 사용해 나눠준다.
접근법을 토대로 문제를 해결하면 아래와 같다.
CREATE PROCEDURE UnpivotProducts()
BEGIN
SET SESSION group_concat_max_len = 1000000;
SET @prepared_stmt = NULL;
SELECT GROUP_CONCAT(CONCAT('SELECT product_id, "', column_name, '" AS store, ', column_name, ' AS price FROM Products WHERE ', column_name, ' IS NOT NULL') SEPARATOR ' UNION ') INTO @prepared_stmt
FROM information_schema.columns
WHERE (
table_name = 'Products'
AND
column_name != 'product_id'
);
PREPARE stmt FROM @prepared_stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END