Имея список обязательных столбцов (хранимая переменная таблицы), проверьте физическую таблицу на наличие нулевых значений в списке обязательных полей. - PullRequest
0 голосов
/ 11 февраля 2020

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

ContactTypeID   FieldID  ColumnName   FieldName
1               1        FirstName    First Name
1               2        LastName     Last Name
1               3        HomePhone    Home Phone
2               1        FirstName    First Name
2               2        LastName     Last Name
2               3        HomePhone    Home Phone      
2               4        Address      Home Address
2               5        Email        Email Address

У меня есть физическая таблица со следующей структурой

ContactID  ContactTypeID  FirstName  LastName  HomePhone     Address  Email
1          1              Mary       Smith     Null          Null     Null
2          1              Jim        Smith     999-999-9999  Null     Null
3          2              Steve      Jones     Null          Null     Null

Я хочу, чтобы результаты для отображения ContactID с значениями null в любой из требуемых обязательных переменных таблицы полей.

Таким образом, исходя из приведенной выше информации, я ожидал бы ContactID с 1 и 3

Я бы предпочел не использовать курсор или динамику c SQL, если нет другого пути.

Ответы [ 3 ]

1 голос
/ 12 февраля 2020

Предполагая, что типы совместимы (скажем, все строки), я бы развернул всю таблицу, используя apply, а затем сравнил и агрегировал:

select distinct ContactId
from physical p cross apply
     (values ('FirstName', FirstName),
             ('LastName', LastName),
             ('HomePhone', HomePhone),
             ('Address', Address),
             ('Email', Email)
     ) v(col, value) join
     required r
     on v.contactTypeId = p.contactTypeId and
        v.col = r.ColumnName
where v.value is null;
0 голосов
/ 12 февраля 2020

Это можно было бы сделать без динамического c SQL, но его нужно было бы жестко закодировать.

Каждый раз, когда вы сохраняете где-нибудь имена столбцов и хотите делать логические операции c на основе этого, скорее всего, это рано или поздно приведет вас к Dynami c SQL.

Более того, он не должен быть неэффективным, так как запрос таблицы с необходимыми полями не займет много времени, так как ( Полагаю, что он не будет большим, и после того, как вы не будете проверять полученные динамические значения c SQL, вы можете создать надлежащие индексы, чтобы уменьшить количество запросов к другой таблице (например, ContactTypeId - хороший кандидат для индекса).

Сказав это, в данном подходе используется функция Dynami c SQL (примечание string_agg, которая доступна в новых SQL серверах), для старых вам необходимо применить другой подход, который можно легко найти на этом сайте я использовал string_agg для краткости):

create table TestTable (ContactID int, ContactTypeID int, FirstName varchar(30), LastName varchar(30), HomePhone varchar(30), Address varchar(30), Email varchar(30));
insert into TestTable values
(1 , 1 ,'Mary' ,'Smith', Null ,Null , Null),
(2 , 1 ,'Jim' ,'Smith', '999-999-9999' ,Null , Null),
(3 , 2 ,'Steve' ,'Jones', Null ,Null , Null);
create table RequiredInfo (ContactTypeID int, FieldID int, ColumnName varchar(30), FieldName varchar(30));
insert into RequiredInfo values
(1, 1, 'FirstName', 'First Name'),
(1, 2, 'LastName', 'Last Name'),
(1, 3, 'HomePhone', 'Home Phone'),
(2, 1, 'FirstName', 'First Name'),
(2, 2, 'LastName', 'Last Name'),
(2, 3, 'HomePhone', 'Home Phone'),
(2, 4, 'Address', 'Home Address'),
(2, 5, 'Email', 'Email Address');

declare @sql as varchar(1000) = 'select * from TestTable where ';
select @sql = @sql + string_agg(clauses, ' or ') from (
    select '( ContactTypeId = ' + cast(ContactTypeId as varchar(10)) + ' and (' +
           string_agg( ColumnName + ' is null', ' or ' ) + ') )' clauses
    from RequiredInfo
    group by contacttypeid
) a

exec (@sql)
0 голосов
/ 12 февраля 2020

Если вам все равно, какие столбцы не заполнены, вы можете использовать следующее решение, которое не использует Dynami c SQL. Просто замените TableA и TableB вашими собственными таблицами. Возможно, вам придется поместить TableB в подзапрос, чтобы преобразовать столбцы в другие типы данных, если выдает жалобу на отключение. При развертывании структуры таблицы вам нужно будет добавить любые столбцы в разворот. В этом примере я предполагаю, что все ваши столбцы данных varchar (50).

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

;WITH TableBProvided AS
(
SELECT ContactId, ContactTypeID, COUNT(ContactTypeId) as FieldsProvided, STRING_AGG(ColumnName,', ') As ColumnNamesProvided 
FROM TableB
UNPIVOT  
   (ColumnValue FOR ColumnName in
      (FirstName, LastName, HomePhone, [Address], Email)  
) AS unpvt
GROUP BY ContactId, ContactTypeID
)
,TableARequired AS
(
SELECT ContactTypeId, Count(FieldId) as RequiredFieldCount, STRING_AGG(ColumnName,', ') As ColumnNamesRequired 
FROM TableA
GROUP BY ContactTypeId
)
SELECT ContactId, FieldsProvided, RequiredFieldCount, ColumnNamesProvided, ColumnNamesRequired FROM TableBProvided TBP
JOIN TableARequired TAR ON TAR.ContactTypeId = TBP.ContactTypeId
WHERE RequiredFieldCount <> FieldsProvided

Если вы хотите специально получить пропущенные поля, вам придется выполнить то, что называется реляционным делением если я правильно помню, это немного над моей головой.

https://www.red-gate.com/simple-talk/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/

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