Преобразование подзапроса SQL в объединение при просмотре другой записи в той же таблице Access 2010 - PullRequest
1 голос
/ 15 ноября 2011

Я читал, что объединения более эффективны, чем подзапросы, у меня очень медленный запрос, который использует много подзапросов, поэтому я хотел бы улучшить его, но не знаю, как.

У меня есть следующие таблицы:

 People  \\this table stores lists of individual people with the following fields
 ( 
    ID, \\Primary Key
    aacode Text, \\represents a individual house
    PERSNO number, \\represent the number of the person in the house e.g. person number 1
    HRP number, \\the PERSNO of the Housing Reference Person (HRP) the "main" person in the house
    DVHsize number, \\the number of people in the house
    R01 number, \\the persons relationship to the person who is PERSNO=1
    R02 number, \\the persons relationship to the person who is PERSNO=2
    R03 number, \\the persons relationship to the person who is PERSNO=3
    AgeCat text, \\the age range of the person e.g. 30-44
    xMarSta number, \\representing the marital satus of the person
)
Relatives \\this table stores the possible R01 numbers and their text equivalents
(
    ID Primary Key, \\all possible R01 values
    Relationship text, \\meaning of the corisponding R01 values
)
xMarSta \\this table store the possible xMarSta values and their text equivalents
(
    ID Primary Key \\all possible xMarSta values
    Marital text, \\meaning of corresponding R01 values
)

Запрос:

HsHld - цель этого запроса состоит в том, чтобы создать для каждого дома (то есть каждого аакода) текстовую строку, описывающую дом в форме [Marital][AgeCat][Relationship][AgeCat][Relationship][AgeCat] и т. Д. Таким образом, выходные данные для дома из трех человек могут выглядеть как Married(30-44)Spouse(30-44)Child(1-4)

Я знаю, что мой текущий код для HsHld ужасен, но он включен ниже:

SELECT People.ID, People.aacode, People.PERSNO, 
       People.HRP, People.DVHsize, xMarSta.Marital,
       [Marital] & " (" & [AgeCat] & ")" & [RAL2] & [RAge2] & 
       [RAL3] & [RAge3] & [RAL4] & [RAge4] & [RAL5] & [RAge5] & 
       [RAL6] & [RAge6] & [RAL7] & [RAge7] & [RAL8] & [RAge8] AS HsTyp,
       (SELECT Fam2.R01  FROM People  AS Fam2  WHERE Fam2.aacode = People.aacode 
        AND Fam2.PERSNO = 2) AS Rel2,
       (SELECT Fam3.R01  FROM People  AS Fam3  WHERE Fam3.aacode = People.aacode 
        AND Fam3.PERSNO = 3) AS Rel3,
       Switch([Rel2] Is Null,Null,[Rel2]=-9,'DNA',[Rel2]=-8,'NoAns',
              [Rel2]=1,'Spouse',[Rel2]=2,'Cohabitee',[Rel2]<7,'Child',
              [Rel2]<10,'Parent',[Rel2]<15,'Sibling',[Rel2]=15,'Grandchild',
              [Rel2]=16,'Grandparent',[Rel2]=17,'OtherRelative',
              [Rel2]=20,'CivilPartner',True,'Other') AS RAL2,
       Switch([Rel3] Is Null,Null,[Rel3]=-9,'DNA',[Rel3]=-8,'NoAns',
              [Rel3]=1,'Spouse',[Rel3]=2,'Cohabitee',[Rel3]<7,'Child',
              [Rel3]<10,'Parent',[Rel3]<15,'Sibling',[Rel3]=15,'Grandchild',
              [Rel3]=16,'Grandparent',[Rel3]=17,'OtherRelative',
              [Rel3]=20,'CivilPartner',True,'Other') AS RAL3,
       (Select FAge2.AgeCat FROM People AS FAge2 
               WHERE FAge2.aacode = People.aacode 
               AND FAge2.PERSNO = 2
       ) AS RAge2,
       (Select FAge3.AgeCat FROM People AS FAge3 
               WHERE FAge3.aacode = People.aacode AND FAge3.PERSNO = 3
       ) AS RAge3
FROM Relatives 
RIGHT JOIN (xMarSta RIGHT JOIN People ON xMarSta.ID=People.xMarSta) 
           ON Relatives.ID=People.R01
WHERE (((People.HRP)=[People.PERSNO]))
ORDER BY People.aacode;

Есть несколько ключевых вещей, которые необходимо изменить.

  1. В настоящее время я не могу получить соединение с поля Rel для родственников. таблица, чтобы работать, поэтому я использую функцию Switch с именем RAL там должен будь лучше.
  2. Для простоты в посте я включил только Rel2 & Rel3 и т. Д., Но в реальном коде он достигает Rel13! Так что проблема производительности еще хуже.
  3. Я хочу заменить эти подзапросы соединениями, но как подзапрос смотрит в другую запись в той же таблице, я не уверен, как идти об этом.
  4. Я очень глубоко разбираюсь в этом, я знаю немного SQL, но Сложность этой проблемы слишком велика для моих ограниченных знаний

Ответы [ 2 ]

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

Самое первое, что у вас есть реляционная ситуация, но ваша структура таблицы использует столбцы для представления отношений. Это дает вам столбцы R01, R02, R03 ... R13 на вашей таблице. К сожалению, вы не сможете резко изменить производительность, потому что ваша структура таблиц повторяется денормализовано, а не реляционно. Это означает, что вашему запросу понадобится весь этот повторяющийся код, как вы упоминали, повторяя 13 раз. Это также означает, что ваша функция переключения может быть заменена соединением, но снова будет повторяться 13 раз.

Верно, теперь вернемся к вашему запросу, у вас есть несколько подвыборов в вашем запросе, и вам нужно объединить связанные таблицы в левом соединении в предложении FROM и использовать новый связанный псевдоним в вашем выборе. теперь вы увидите на примере ниже, что для каждого поля R01, R02 у вас будет отношение Fam2, Fam3, и вам нужно будет сделать это 13 раз для вашего случая, и для каждого из них вам нужно связать таблицу родственников (как я назвал Relat2, Relat3 и т. д.). Теперь, если вы можете изменить структуру вашей базы данных для нормализованной структуры, вы могли бы действительно упростить этот запрос и использовать гораздо более простые объединения.

Посмотрите, поможет ли этот вам понять процесс:

SELECT People.ID, People.aacode, People.PERSNO,  
       People.HRP, People.DVHsize, xMarSta.Marital, 
       [Marital] & " (" & [People.AgeCat] & ")" & [RAL2] & [RAge2] &  
       [RAL3] & [RAge3] AS HsTyp, 
       Fam2.R01 AS Rel2,
       Fam3.R01 AS Rel3, 
       Relat2.Relationship as RAL2,
       Relat3.Relationship as RAL3,
       Fam2.AgeCat AS RAge2, 
       Fam3.AgeCat AS RAge3 
FROM (((((People
LEFT JOIN (People  AS Fam2) ON (Fam2.aacode = People.aacode  and Fam2.PERSNO = 2))
LEFT JOIN (Relatives as Relat2) on Relat2.Id = Fam2.R01)
LEFT JOIN (People as Fam3)   ON (Fam3.aacode = People.aacode  AND Fam3.PERSNO = 3))
LEFT JOIN (Relatives as Relat3) on Relat3.Id = Fam3.R01)
LEFT JOIN xMarSta ON xMarSta.ID=People.xMarSta)
WHERE (People.HRP=[People.PERSNO])
ORDER BY People.aacode; 
0 голосов
/ 15 ноября 2011

Само присоединение таблицы к ней выполняется с псевдонимом

, например

Выбрать * Из [Table1] Присоединиться к [Table1] t1 на T1.SomeField = Table1.SomeOtherField

и т.д ..

Пробали не успеет это исправить, но настоящая проблема в том, что вы денормализовали с R01, R02 и т. Д.

У вас должен быть другой стол RelationshipId PersonFrom PersonTo

Это необходимо сделать при создании отношений, и это будет означать изменения в вашем пользовательском интерфейсе и логике.

...