Хранимая процедура, которая принимает динамическое количество соединений - PullRequest
0 голосов
/ 22 октября 2019

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

SELECT a.Account
FROM Database.Accounts a
JOIN (SELECT Table_Name FROM Database.TableStrings WHERE Row = 1) b ON a.Account = b.Account
JOIN (SELECT Table_Name FROM Database.TableStrings WHERE Row = 2) c ON a.Account = c.Account
JOIN (SELECT Table_Name FROM Database.TableStrings WHERE Row = 3) d ON a.Account = d.Account
...
/*Where the number of joins is equal to COUNT(Table_Name) FROM Database.TableStrings*/

или

first = SELECT a.Account
        FROM Database.Accounts a
        JOIN (SELECT Table_Name FROM Database.TableStrings WHERE Row = 1) b ON a.Account = b.Account

second = SELECT a.Account
         FROM first a
         JOIN (SELECT Table_Name FROM Database.TableStrings WHERE Row = 2) b ON a.Account = b.Account
...

Ниже приведен пример таблиц и ожидаемого результата:

---Database.Accounts---
Account (Integer)
------------------------
111
222
333
444
555

---Database.TableStrings---
Table_Name (String):
------------------------
'Database.HasPhoneNumber'
'Database.HasEmail'
'Database.HasBankAccount'

---Database.HasPhoneNumber---
Account (Integer)
------------------------
111
444

---Database.HasEmail---
Account (Integer)
------------------------
111
222


---Database.HasBankAccount---
Account (Integer)
------------------------
111
222
555

С примерами таблиц ожидаемый результат будетСчет 111.

Мне трудно представить, как это сделать в хранимой процедуре, если это вообще возможно.

Ответы [ 3 ]

1 голос
/ 22 октября 2019

вы можете рассмотреть возможность использования рекурсивных запросов (cte) для обработки конкатенации строк. и запустите sp_executesql для выполнения сгенерированного запроса строки SQL

позволяет также генерировать псевдонимы вашей таблицы, используя char()

declare @strSQL nvarchar(max), @strSQLjoin nvarchar(max)

set @strSQL = 'SELECT a.Account
    FROM Database.Accounts a ';

set @strSQLjoin = '';


with cte as (
    select 'Database.PhoneNumbers' as TableStrings
    union all select 'Database.Emails'
    union all select 'Database.BankAccounts'
), cte2 as (
    select TableStrings, (char(row_number() over (order by TableStrings) + 97)) as tbl 
    from cte)
    select @strSQLjoin = coalesce(@strSQLjoin 
        + ' JOIN (SELECT Table_Name FROM '+TableStrings+') '+tbl+' ON a.Account = '+tbl+'.Account '
        ,' JOIN (SELECT Table_Name FROM '+TableStrings+') '+tbl+' ON a.Account = '+tbl+'.Account')      
    from cte2;

set @strSQL=@strSQL + @strSQLjoin;
print @strSQL
exec sp_executesql @strSQL
0 голосов
/ 22 октября 2019

на основе данных примера и примера запроса вы можете достичь желаемого без использования динамического запроса

-- sample table
declare @Accounts table
(
    Account int
)

declare @TableStrings table
(
    Table_Name  varchar(100),
    Account     int
)

-- sample data
insert into @Accounts
values (111), (222), (333), (444), (555)

insert into @TableStrings
values ('Database.HasPhoneNumber', 111), ('Database.HasPhoneNumber', 444),
       ('Database.HasEmail', 111),       ('Database.HasEmail', 222),
       ('Database.HasBankAccount', 111), ('Database.HasBankAccount', 222),
       ('Database.HasBankAccount', 555)

select  a.Account
from    @Accounts a
        inner join @TableStrings t  on  a.Account   = t.Account
group by a.Account
having count(*) = (select count(distinct Table_Name) from  @TableStrings)
0 голосов
/ 22 октября 2019

Я понимаю, что это не совсем то, что вы просили. Но поскольку добавление новых строк в таблицу TableStrings уже подразумевает изменения схемы (создание новых таблиц), на этом этапе вы также можете соответствующим образом обновить хранимую процедуру вместо использования динамического SQL

Если это вариант, например, вашзапрос может выглядеть как

SELECT a.Account
FROM Database.Accounts a
 where exists (select 1 from Database.HasPhoneNumber e where e.Account = a.Account)
   and exists (select 1 from Database.HasEmaile e where e.Account = a.Account)
   and exists (select 1 from Database.HasBankAccount e where e.Account = a.Account)
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...