Вставить отсутствующие значения в таблицу, используя SQL - PullRequest
0 голосов
/ 10 июля 2020

Цель: мне нужно полностью заполнить таблицу матрицей значений для каждого столбца с помощью группировки [PropertyId]. Некоторые [PropertyId] имеют все необходимые значения для каждого столбца (Таблица 1), однако во многих отсутствуют некоторые значения (Таблица 2). Кроме того, не каждому [PropertyId] нужны эти значения, поскольку они имеют совершенно разные региональные значения. Следовательно, мне нужно определить, какие [PropertyId] нуждаются в заполнении значений и не имеют всех необходимых значений.

Примеры: Таблица 1. Каждая идентифицированная группа [PropertyId] должна иметь 23 отдельных записи для этих четырех столбцы [ReportingVolumeSettingId], [SpeciesGroupInventoryID], [CropCategoryID], [SortOrder].

enter image description here

Table 2. Here is an example of a PropertyID that is missing a value combination as it only has 22 records:

PropertID 2 не имеет всех необходимых значений

Результаты обоих этих примеров были запрошены из одной и той же таблицы [ReportingVolume]. Мне не удалось даже определить, какая комбинация записей для [PropertyID] отсутствует. Я хотел бы идентифицировать каждую недостающую комбинацию записей, а затем вставить эту комбинацию записей в таблицу [ReportingVolume].

Проблема, которую необходимо решить - Код SQL ниже - это моя попытка 1. Определить правильный список Ценности; 2. Определите, какие свойства должны иметь совпадающие значения; 3. Определите, в каких свойствах отсутствуют значения; 4. Определите недостающие значения для каждого свойства.

    ;with CORRECT_LIST as
(
select 
SpeciesGroupInventoryName, SpeciesGroupInventoryId, CropCategoryName,CropCategoryID, UnitOfMeasure, SortOrder
--*
from [GIS].[RST].[vPropertyDefaultTimberProductAndUnitOfMeasure]
where PropertyId in (1)
)
,
property_list as
(
select distinct rvs.propertyid as Volume_Property, pd.PropertyName, pd.PropertyId from RMS.GIS.ReportingVolumeSetting rvs
right outer JOIN RMS.GIS.PropertyDetail AS pd ON rvs.PropertyId = pd.PropertyId 
left outer  JOIN RMS.GIS.SpeciesGroupInventory AS sgi ON rvs.SpeciesGroupInventoryId = sgi.SpeciesGroupInventoryId
where sgi.SpeciesGroupInventoryId in (1,2,3)
or pd.PropertyId = 171
)
, Partial_LISTS as
(
select Count(distinct ReportingVolumeSettingId) as CNT_REPORT, pd.PropertyName, pd.PropertyId
from [GIS].[ReportingVolumeSetting] rvs
right outer JOIN property_list AS pd ON rvs.PropertyId = pd.PropertyId 
group by pd.propertyId, pd.PropertyName
)
, Add_Props as
(
select propertyName, propertyId, SUM(CNT_REPORT) as CNT_RECORDS from Partial_LISTS
where CNT_REPORT < 23
group by propertyName, propertyId
)
, RVS_RECORDS_PROPS as
(
select addProps.PropertyName, rvs.* from [GIS].[ReportingVolumeSetting] rvs
join Add_Props addProps on addprops.PropertyId = rvs.PropertyID
where rvs.PropertyId in (select PropertyId from Add_Props)
)
select rp.PropertyName, cl.*, rp.SpeciesGroupInventoryId from correct_list cl
left outer join RVS_Records_Props rp 
    on rp.SpeciesGroupInventoryId = cl.SpeciesGroupInventoryId
    and rp.CropCategoryId = cl.CropCategoryID
    and rp.SortOrder = cl.SortOrder
Order by rp.PropertyName

Как я могу изменить код или создать новый блок кода, который определяет недостающие значения и вставляет их в таблицу по PropertyId?

I Я использую SQL SMSS v15.

Большое спасибо.

Ответы [ 2 ]

1 голос
/ 11 июля 2020

Это должно определить недостающие записи. Вы можете просто добавить поверх этого команду INSERT INTO. Имейте в виду, что ReportingVolumeSettingId уникален и неизвестен, поэтому здесь он не рассматривается.

SELECT * FROM (SELECT DISTINCT PropertyId FROM ReportingVolume) rv
CROSS APPLY 
(
    SELECT DISTINCT SpeciesGroupInventoryId
        , CropCategoryId
        , SortOrder
    FROM ReportingVolume
) x
EXCEPT
SELECT PropertyId, SpeciesGroupInventoryId, CropCategoryId, SortOrder FROM ReportingVolume
0 голосов
/ 10 июля 2020

У меня нет доступа к вашим данным, поэтому я не могу предоставить конкретный пример c для вашей среды, но я могу предоставить вам простой пример с использованием SQL серверного оператора EXCEPT.

Выполните следующий пример в SSMS:

-- Create a list of required values.
DECLARE @Required TABLE ( required_id INT, required_val VARCHAR(50) );
INSERT INTO @Required ( required_id, required_val ) VALUES
    ( 1, 'Required value 1.' ), ( 2, 'Required value 2.' ), ( 3, 'Required value 3.' ), ( 4, 'Required value 4.' ), ( 5, 'Required value 5.' );

-- Create some sample data to compare against.
DECLARE @Data TABLE ( PropertyId INT, RequiredId INT );
INSERT INTO @Data ( PropertyId, RequiredId ) VALUES
    ( 1, 1 ), ( 1, 2 ), ( 1, 3 ), ( 2, 1 ), ( 2, 2 ), ( 2, 4 ), ( 2, 5 );

-- Set a property id value to query.
DECLARE @PropertyId INT = 1;

-- Preview @Data's rows for the specified @PropertyId.
SELECT * FROM @Data WHERE PropertyId = @PropertyId ORDER BY PropertyId, RequiredId;

На этом этапе я создал список требуемых значений (required_id от 1 до 5) и некоторые фиктивные данные для их проверки. Этот начальный SELECT показывает текущий набор результатов для указанного @PropertyID:

+------------+------------+
| PropertyId | RequiredId |
+------------+------------+
|          1 |          1 |
|          1 |          2 |
|          1 |          3 |
+------------+------------+

Вы можете видеть, что required_id значения 4 и 5 равны отсутствует для текущего свойства. Затем мы можем сравнить @Required с @Data и INSERT любые отсутствующие обязательные значения с помощью оператора EXCEPT и затем вернуть исправленный набор результатов.

-- Insert any missing required values for @PropertyId.
INSERT INTO @Data ( PropertyId, RequiredId )
SELECT @PropertyId, required_id FROM @Required
EXCEPT
SELECT PropertyId, RequiredId FROM @Data WHERE PropertyId = @PropertyId;

-- Preview @Data's revised rows for @PropertyId.
SELECT * FROM @Data WHERE PropertyId = @PropertyId ORDER BY PropertyId, RequiredId;

Обновленный набор результатов теперь выглядит следующим образом:

+------------+------------+
| PropertyId | RequiredId |
+------------+------------+
|          1 |          1 |
|          1 |          2 |
|          1 |          3 |
|          1 |          4 |
|          1 |          5 |
+------------+------------+

Вы можете запустить это снова для @PropertyId = 2, чтобы увидеть другой сценарий.

Обратите внимание на порядок использования EXCEPT. Сначала идут требуемые строки, за ними следует оператор EXCEPT, а затем текущие строки, которые необходимо проверить. Это важно. EXCEPT говорит, что покажите мне строки из @Required, которых нет в @ Data - что позволяет вставлять любые отсутствующие требуемые значения в @ Data.

Я знаю, что этот пример не представляет ваши существующие данные с Требуется 23 строки, но, надеюсь, это поможет вам найти решение для ваших нужд. Вы можете узнать больше об операторе EXCEPT здесь .

Вот полный пример SSMS:

-- Create a list of required values.
DECLARE @Required TABLE ( required_id INT, required_val VARCHAR(50) );
INSERT INTO @Required ( required_id, required_val ) VALUES
    ( 1, 'Required value 1.' ), ( 2, 'Required value 2.' ), ( 3, 'Required value 3.' ), ( 4, 'Required value 4.' ), ( 5, 'Required value 5.' );

-- Create some sample data to compare against.
DECLARE @Data TABLE ( PropertyId INT, RequiredId INT );
INSERT INTO @Data ( PropertyId, RequiredId ) VALUES
    ( 1, 1 ), ( 1, 2 ), ( 1, 3 ), ( 2, 1 ), ( 2, 2 ), ( 2, 4 ), ( 2, 5 );

-- Set a property id value to query.
DECLARE @PropertyId INT = 1;

-- Preview @Data's rows for the specified @PropertyId.
SELECT * FROM @Data WHERE PropertyId = @PropertyId ORDER BY PropertyId, RequiredId;

-- Insert any missing required values for @PropertyId.
INSERT INTO @Data ( PropertyId, RequiredId )
SELECT @PropertyId, required_id FROM @Required
EXCEPT
SELECT PropertyId, RequiredId FROM @Data WHERE PropertyId = @PropertyId;

-- Preview @Data's revised rows for @PropertyId.
SELECT * FROM @Data WHERE PropertyId = @PropertyId ORDER BY PropertyId, RequiredId;
...