У меня есть таблица «ABC», в которой есть столбцы «prod1_name», «prod1_percentage», prod2_name, prod2_percentage и так далее до prod15_name, prod15_percentage. Каждый столбец (от 1 до 15) может иметь или не иметь значение.
Вопрос - как я могу использовать цикл для получения ненулевых значений из столбцов вместо перечисления имен каждого столбца в SQL SELECT?

просто добавил ссылку на картинку в свой вопрос, чтобы проиллюстрировать, что я имел в виду


Я не уверен, что понимаю вопрос, но вот несколько вариантов:
Вы можете получить список схем, таблиц и столбцов для любой таблицы, запросив системные представления.
SELECT s.name, o.name, c.name
FROM sys.schemas s
INNER JOIN sys.objects o
ON o.schema_id = s.schema_id
INNER JOIN sys.columns c
ON c.object_id = o.object_id
WHERE s.name = @schemaName
AND o.name = @tableName
Вы можете вставить это в курсор, если вам нужно сделать с ними что-то динамическое, добавив к приведенному выше префиксу что-то вроде:
DECLARE schemaRunner CURSOR FAST_FORWARD FOR
Оттуда измерьте @@ FETCH_STATUS в цикле while, чтобы захватить ваши переменные и что-то с ними сделать:
--cursor definition
OPEN schemaRunner
FETCH NEXT FROM shcemaRunner into @sName, @tName, @cName
WHILE @@FETCH_STATUS = 0
BEGIN
--...DO SOMETHING TO THE VARIABLES HERE
FETCH NEXT FROM shcemaRunner into @sName, @tName, @cName
END
CLOSE schemaRunner
DEALLOCATE schemarunner
Теперь по вашему вопросу - не выбирать столбцы, если они нулевые - так что, если все строки имеют их нулевые? Итак, вы можете измерить это в части DO SOMETHING выше, и добавить или пометить столбцы, если они вернутся истинными, так что ...
DECLARE @SQL NVARCHAR(MAX) = N'' -- THIS LINE SHOULD BE OUTSIDE, BEFORE THE LOOP.
SET @SQL = 'IF EXISTS (SELECT TOP 1 1 FROM ABC WHERE ' + @cName + ' IS NOT NULL) INSERT INTO <someTrackingTable> VALUES (''' + @cName + ''')'
EXEC SP_EXECUTESQL @SQL
Затем, после запуска цикла, вы можете создать список столбцов для своего оператора:
SELECT STUFF((
SELECT ', ' + Name
FROM <someTrackingTable>
FOR XML PATH('')
), 1, 2,'') AS Columns
Это немного сложно, но вы просите сложный предмет.
Спасибо за ответ. Я только что добавил картинку в свой вопрос, чтобы проиллюстрировать, что я имел в виду. Есть ли какой-нибудь простой оператор, который я могу встроить в sql select, чтобы достичь того, чего я хочу?
Это операция unpivot. Я бы использовал cross apply:
select t.productid, v.mixcomponent, v.mixpercentage
from t cross apply
(values (mix1component, mix1percentage),
(mix2component, mix2percentage),
(mix3component, mix3percentage),
(mix4component, mix4percentage),
. . .
) v(mixcomponent, mixpercentage)
where mixcomponent is not null;
Как насчет использования «ВЫБРАТЬ * ИЗ 'ABC'»?