2014-09-29 2 views
1

Часть сущностей базы данных SQL Server являются:Какая часть моего SQL-запроса неверна?

  • Формы (Id, счетчик)
  • Группы (Id, form_id, счетчик)
  • Fields (Id, GROUP_ID, счетчик)

Логика этой структуры:

  • Счетчик полей может быть 0 или более
  • Счетчик групп зависит от счетчиков полей, которые существуют в этой группе: значение счетчика каждого поля, которое больше 0, увеличивает счетчик группы на один
  • Та же связь существует между группой и формой: счетчик формы - это сумма счетчики в группы, которые выше, чем 0

небольшой пример для лучшего понимания:

Form A1 (Counter: 1) 
|-> Group BB1 (Counter: 2) 
    |-> Field CCC1 (Counter: 2) 
    |-> Field CCC2 (Counter: 1) 
|-> Group BB2 (Counter: 0) 
    |-> Field CCC3 (Counter: 0) 
    |-> Field CCC4 (Counter: 0) 
Form A2 
... 

Некоторые поля содержит недопустимые значения, что мой запрос нужно проверить. Но я не могу написать это правильно. Последняя версия этого:

select distinct 
     cd.Id as [FormID], 
     sum (case when cd.Counter > 0 then 1 else 0 end) over (partition by cd.Id, gd.Id, fd.Id) as [FormSum], 
     cd.Counter as [FormVal], 

     gd.Id as [GroupID], 
     sum(case when gd.Counter > 0 then 1 else 0 end) over (partition by cd.Id, gd.Id, fd.Id) as [GroupSum], 
     gd.Counter as [GroupVal], 

     fd.Id as [FieldID], 
     --sum(case when fd.Counter > 0 then 1 else 0 end) over (partition by cd.Id, gd.Id) as [FieldSum], 
     fd.Counter as [FieldVal] 
    from FieldDatas fd 
    inner join GroupDatas gd on fd.GroupData_Id = gd.Id 
    inner join CrfDatas cd on gd.CrfData_Id = cd.Id 
    where cd.Id in 
    (
     -- some subquery 
    ) 
    order by cd.Id, gd.Id, fd.Id 

Update:
Этот запрос должен сравнить сохраненные данные Счетчики во всех субъектах с запросом рассчитанным значениями, и зафиксировать эти значения в будущем.

Будем рады любой помощи.

+2

ddl и данные примера вместе с четким объяснением того, что вы хотите, чтобы ваш запрос выполнял долгий путь, чтобы получить ответ. sqlfiddle.com - отличное место для начала. –

ответ

1

Вы не можете обновить содержимое двух таблиц одним запросом, поэтому мы закончим с двумя операторами UPDATE. Затем исправьте «нижнее» отношение (Группы/Поля) до «верхнего». Шаги я взял:

Сначала установите тестовые структуры и данные:

-- Set up test tables 
CREATE TABLE Forms 
(Id int not null 
,Counter int not null) 

CREATE TABLE Groups 
(Id int not null 
,Form_id int not null 
,Counter int not null) 

CREATE TABLE Fields 
(Id int not null 
,Group_Id int not null 
,Counter int not null) 


-- Set up valid test data 
DELETE Forms DELETE Groups DELETE Fields 
INSERT Forms values 
    (1,1) 
INSERT Groups values 
    (1,1,2) 
,(2,1,0) 
INSERT Fields values 
    (1,1,2) 
,(2,1,1) 
,(3,2,0) 
,(4,2,0) 


-- Set invalid Forms counter 
DELETE Forms DELETE Groups DELETE Fields 
INSERT Forms values 
    (1,2) 
INSERT Groups values 
    (1,1,2) 
,(2,1,0) 
INSERT Fields values 
    (1,1,2) 
,(2,1,1) 
,(3,2,0) 
,(4,2,0) 


-- Set invalid Groups counter (both) 
DELETE Forms DELETE Groups DELETE Fields 
INSERT Forms values 
    (1,2) 
INSERT Groups values 
    (1,1,0) 
,(2,1,1) 
INSERT Fields values 
    (1,1,2) 
,(2,1,1) 
,(3,2,0) 
,(4,2,0) 


-- Mondo invalid 
DELETE Forms DELETE Groups DELETE Fields 
INSERT Forms values 
    (1,0) 
INSERT Groups values 
    (1,1,0) 
,(2,1,1) 
INSERT Fields values 
    (1,1,2) 
,(2,1,1) 
,(3,2,0) 
,(4,2,0) 

Далее определить плохие данные в «нижнем» установлено:

-- Detect bad data in Groups/Fields relationship 
SELECT 
    gr.Id 
    ,gr.Counter 
    ,sum(case when fi.Counter <> 0 then 1 else 0 end) CalcValue 
from Groups gr 
    left outer join Fields fi 
    on fi.Group_Id = gr.Id 
group by 
    gr.Id 
    ,gr.Counter 
having sum(case when fi.Counter <> 0 then 1 else 0 end) <> gr.Counter 

использовать это в качестве подзапроса в обновлении заявление:

-- Reset invalid Forms counters 
UPDATE Groups 
set Counter = xx.CalcValue 
from Groups gr 
    inner join (-- Detect bad data in Groups/Fields relationship 
       select 
       gr.Id 
       ,gr.Counter 
       ,sum(case when fi.Counter <> 0 then 1 else 0 end) CalcValue 
       from Groups gr 
       left outer join Fields fi 
       on fi.Group_Id = gr.Id 
       group by 
       gr.Id 
       ,gr.Counter 
       having sum(case when fi.Counter <> 0 then 1 else 0 end) <> gr.Counter) xx 
    on xx.Id = gr.Id 

Вырезать, вставить, переименовать в «верхней» установлено:

-- Detect bad data in Forms/Groups relationship 
SELECT 
    fo.Id 
    ,fo.Counter 
    ,sum(case when gr.Counter <> 0 then 1 else 0 end) CalcValue 
from Forms fo 
    left outer join Groups gr 
    on gr.Form_Id = fo.Id 
group by 
    fo.Id 
    ,fo.Counter 
having sum(case when gr.Counter <> 0 then 1 else 0 end) <> fo.Counter 


-- Reset invalid Forms counters 
UPDATE Forms 
set Counter = xx.CalcValue 
from Forms fo 
    inner join (-- Detect bad data in Forms/Groups relationship 
       select 
       fo.Id 
       ,fo.Counter 
       ,sum(case when gr.Counter <> 0 then 1 else 0 end) CalcValue 
       from Forms fo 
       left outer join Groups gr 
       on gr.Form_Id = fo.Id 
       group by 
       fo.Id 
       ,fo.Counter 
       having sum(case when gr.Counter <> 0 then 1 else 0 end) <> fo.Counter) xx 
    on xx.Id = fo.Id 

Run только обновление в этом порядке и обзор результаты:

SELECT * from Forms 
SELECT * from Groups 
SELECT * from Fields 

Предположение: данные чисты и, как описано, индексы правильно установлены, если таблицы большие, другие непредвиденные расхождения не приходят вверх.

+0

Отлично, спасибо. Очень ясно – dotFive

Смежные вопросы