SQLite: обратный разворот таблицы


Если есть "широкая" таблица со множеством колонок -
то слепить их в столбик достаточно легко с помощью операции UNION

.headers on
.mode column

CREATE TABLE products (
    id INTEGER PRIMARY KEY,
    prod1 INTEGER NOT NULL,
    prod2 INTEGER NOT NULL,
    prod3 INTEGER NOT NULL,
    prod4 INTEGER NOT NULL
);

INSERT INTO products (prod1, prod2, prod3, prod4) VALUES (1,2,3,4);

-- Обратный разворот таблицы
SELECT 'Prod 1' as prod_name, prod1 as prod_qnt FROM products
UNION SELECT 'Prod 2', prod2 FROM products
UNION SELECT 'Prod 3', prod3 FROM products
UNION SELECT 'Prod 4', prod4 FROM products
;

В более общем случае столбцы prod1, prod2,... могут быть произвольно
перемешаны. Тогда корректный обратный разворот делается с помощью
прямого декартова произведения между развернутой таблицей и таблицей,
содержащей список наименований:

.headers on
.mode column


CREATE TABLE products (
    prod_id INTEGER PRIMARY KEY,
    prod_name VARCHAR(50)
);

INSERT INTO products(prod_id, prod_name) VALUES (1, 'Prod 1');
INSERT INTO products(prod_id, prod_name) VALUES (2, 'Prod 2');
INSERT INTO products(prod_id, prod_name) VALUES (3, 'Prod 3');
INSERT INTO products(prod_id, prod_name) VALUES (4, 'Prod 4');


CREATE TABLE variants (
    id INTEGER PRIMARY KEY,
    f1 INTEGER NOT NULL,
    f2 INTEGER NOT NULL,
    f3 INTEGER NOT NULL,
    f4 INTEGER NOT NULL
);

INSERT INTO variants (f1, f2, f3, f4) VALUES ('Prod 4', 'Prod X', 'Prod 2', 'Prod 1');

SELECT Y.*,
	CASE WHEN X.f1=Y.prod_name THEN 'f1'
	WHEN X.f2=Y.prod_name THEN 'f2'
	WHEN X.f3=Y.prod_name THEN 'f3'
	WHEN X.f4=Y.prod_name THEN 'f4' END AS fname
FROM
(SELECT * FROM variants) X, (SELECT * FROM products) Y
;

Здесь в третьем столбце отображатся поле, в котором находится
искомый по списку наименований товар.