Как уже упоминалось, в SQL нет чистого способа реализации таблиц с динамически изменяющимся числом столбцов. Единственные два решения, которые я использовал ранее:
1. Фиксированное число Self-Joins, дающее фиксированное количество столбцов (AS на BobInce)
2. Сгенерируйте результаты в виде строки в одном столбце
Второй звучит поначалу гротескно; хранить идентификаторы в виде строки ?! Но когда вывод форматируется как XML или что-то еще, люди, кажется, не особо обращают на это внимание.
Точно так же, это очень мало полезно, если вы хотите объединить результаты в SQL. Если результат должен быть представлен в приложении, он может быть очень подходящим. Лично я предпочитаю делать выравнивание в приложении, а не в SQL
Я застрял здесь на 10-дюймовом экране без доступа к SQL, поэтому я не могу дать протестированный код, но основным методом было бы каким-то образом использовать рекурсию;
- Рекурсивная скалярная функция может сделать это
- MS SQL может сделать это с помощью рекурсивного оператора WITH (более эффективно)
Скалярная функция (что-то вроде):
CREATE FUNCTION getGraphWalk(@child_id INT)
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE @graph VARCHAR(4000)
-- This step assumes each child only has one parent
SELECT
@graph = dbo.getGraphWalk(parent_id)
FROM
mapping_table
WHERE
category_id = @child_id
AND parent_id IS NOT NULL
IF (@graph IS NULL)
SET @graph = CAST(@child_id AS VARCHAR(16))
ELSE
SET @graph = @graph + ',' + CAST(@child_id AS VARCHAR(16))
RETURN @graph
END
SELECT
category_id AS [category_id],
dbo.getGraphWalk(category_id) AS [graph_path]
FROM
mapping_table
ORDER BY
category_id
Раньше я не использовал рекурсивный оператор WITH, но я попробую синтаксис, хотя у меня нет здесь SQL, чтобы что-то тестировать:)
Рекурсивный СО
WITH
result (
category_id,
graph_path
)
AS
(
SELECT
category_id,
CAST(category_id AS VARCHAR(4000))
FROM
mapping_table
WHERE
parent_id IS NULL
UNION ALL
SELECT
mapping_table.category_id,
CAST(result.graph_path + ',' + CAST(mapping_table.category_id AS VARCHAR(16)) AS VARCHAR(4000))
FROM
result
INNER JOIN
mapping_table
ON result.category_id = mapping_table.parent_id
)
SELECT
*
FROM
result
ORDER BY
category_id
РЕДАКТИРОВАТЬ - ВЫХОД для обоих одинаков:
1 '1'
2 '1,2'
3 '1,2,3'
4 '1,2,4'
5 '1,2,5'
6 '1,6'
7 '1,6,7'
8 '1,6,7,8'
9 '1,6,9'