Вставить процедуру столбца в таблицу - PullRequest
0 голосов
/ 24 ноября 2011

У меня вопрос о вставке хранимой процедуры столбца в таблицу.У меня есть две таблицы около 100 строк и 1 мил строк.По сути, у меня есть функция, которая возвращает int, сравнивая две данные из разных таблиц.И я хочу запустить функцию для каждой комбинации данных.

Таблица 1 (~ 100 строк)

Col1                
A                   
B                   
C                   
D  

Таблица 2 (~ 1 млн строк)

Col1  
1  
2  
3  
4  

function(i,j), где i из таблицы 1и j из таблицы 2
Код в двух словах выглядит следующим образом:

while i < count(*) table 1  
   print i  
   while j < count(*) table 2  
   select function(i,J)  
   J = J + 1  
   end  
i = i + 1  
j = 0  
end  

Отображение результата представляет собой длинный столбец с i (из таблицы 1) и значением int, вычисленным из функции.

i(1)  
1  
3  
4  
.  
.  
.  
i(2)  
1  
2  
.  
.  

Я хочу отобразить приведенный выше результат в виде таблицы, в которой динамически присваивается имя столбца i.

i(1)        i(2)        i(3) .....  
1           1           5  
3           2           9  
4           3           4  

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 24 ноября 2011

Это будет дорого, 100 000 000 результатов! Поддержка в SQlserver очень плохая для этого.

Чтобы использовать sp_crosstab (который не входит в число наиболее желательных для выполнения задач), вам нужно три столбца

Так что это были бы 'I', 'J' и f (i, j)

вместо циклов while вы можете делать то, что обычно является ошибкой.

Выберите Table1.Col1, Table2.Col1, Функция (Table1.Col1, Table2.Col2) Из таблицы 1, таблицы 2

(или из таблицы 1 Присоединиться к таблице 2)

Это дает декартово произведение всех 100 записей в таблице 1, объединенных со всеми 1 000 000 в таблице 2. Передайте это правильно в sp_crosstab, и вы получите строку для каждого значения в Table2, столбец для каждой строки в Table1 и ячейку, содержащую результат функции.

Сказав это, не удивляйтесь, если это немного медленно, и, возможно, занимает немного памяти ....

Возможно, вы захотите попробовать его с некоторыми меньшими диапазонами.

0 голосов
/ 24 ноября 2011

Это было бы моим решением:

DECLARE @columns VARCHAR(MAX)

SELECT @columns = COALESCE(@columns + ',[' + CAST(t1.i as varchar(10)) + ']'
                           ,'[' + CAST(t1.i as varchar(10)) + ']')
FROM t1

DECLARE @query VARCHAR(MAX)
SET @query = '
    SELECT * FROM
    (
        SELECT t1.i, t2.j, yourFunction(t1.i, t2.j) as functionResult
        FROM t1
        CROSS JOIN t2
    ) as tbl3
    PIVOT
    (
        SUM(functionResult) FOR i in (' + @columns + ')
    ) AS tblResults'

EXECUTE (@query)​

Вы можете проверить рабочий пример этого здесь, на SEDE .

Редактировать

И просто для пояснения, вы бы заменили t1 и t2 фактическими именами ваших 2 таблиц. Также в примере SEDE я просто добавил i и j вместе (t1.i + t2.j as functionResult), потому что я не могу создавать функции там, но вы бы просто вызвали вашу функцию вместо этого, как я покажу в своем ответе (yourFunction(t1.i, t2.j) as functionResult) .

0 голосов
/ 24 ноября 2011

Чтобы получить желаемый результат, см. Ниже кодирование, я прекрасно кодировал, поэтому вам нужно только изменить имя таблицы и соответственно вызвать вашу функцию в закомментированной области в блоке кода.

DECLARE @rest INT,
        @rev INT,
        @counter INT,
        @Table1Count INT,
        @Table2Count INT
DECLARE @colName VARCHAR(50),
        @Fields NVARCHAR(MAX),
        @Sql VARCHAR(MAX)

SELECT @colName = 'Col', @Fields = '', @rest = 1, @rev = 1, @counter = 1
SELECT @Table1Count = count(*) from Table1
SELECT @Table2Count = count(*) from Table2

CREATE TABLE #temp (ID INT IDENTITY(1,1), defaultColumn VARCHAR(50))
WHILE @rest <= @Table2Count
    BEGIN
        INSERT INTO #temp (defaultColumn) VALUES(@rest)
        SET @rest = @rest + 1
    END

WHILE @counter <= @Table1Count
    BEGIN
        PRINT(CAST(@counter AS VARCHAR))
        SET @colName = @colName+CAST(@counter AS VARCHAR)
        SET @Fields = @Fields + @colName
        IF @counter <> @Table1Count
        BEGIN
            SELECT @Fields = @Fields +', '
        END
        EXEC ('ALTER TABLE #temp ADD '+ @colName +' VARCHAR(250)')

        WHILE  @rev <= @Table2Count
            BEGIN
                -------------------------------------------------
                -- Some modification may need to your Function
                -- CALL YOUR FUNCTIN HERE
                -------------------------------------------------
                SET @Sql = 'UPDATE #temp SET '+ @colName +' = '+ CAST( @rev AS VARCHAR) 
                            +' WHERE defaultColumn = '+ CAST( @rev AS VARCHAR)
                EXEC (@Sql)
                SET @rev = @rev + 1
            END 

        SELECT @rev = 1, @counter = @counter +1, @colName = 'Col'
    END
 EXEC('SELECT '+ @Fields + ' FROM #temp')
 DROP TABLE #temp

Имейте в виду, что попробуйте использовать столбцы ниже максимально допустимого количества столбцов в таблице в соответствии с сервером MSSQL (используемой версией).

Надеюсь, это будет очень полезно для вас, спасибо за ваше время

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...