2015-12-08 3 views
2
CREATE TABLE PERSON 
(
    persID  INT IDENTITY(1,1) PRIMARY KEY, 
    persFName VARCHAR(30) NOT NULL, 
    persLName VARCHAR(30) NOT NULL, 
    persDOB  DATE, 
    motherID INT FOREIGN KEY REFERENCES person(persID), 
    fatherID INT FOREIGN KEY REFERENCES person(persID), 
    persDOD  DATE, 
    persGender CHAR(1), 
) 

CREATE TABLE COUPLE 
(
    coupleID INT  IDENTITY(1,1) PRIMARY KEY, 
    alphaSpouse INT  NOT NULL FOREIGN KEY REFERENCES person(persID), 
    omegaSpouse INT  NOT NULL FOREIGN KEY REFERENCES person(persID), 
    coupleStart DATE NOT NULL, 
    coupleEnd DATE, 
) 

INSERT INTO person (persFName, persLName, persDOB, motherID, fatherID, persDOD, persGender) VALUES 
('Jim', 'Smith', '1920-05-15', NULL, NULL, '2001-04-21','M'), 
('Agnes', 'Smith', '1922-09-21', NULL, NULL, '2003-06-01','F'), 
('Linda', 'Howard', '1949-03-20', 2, 1, NULL,'F'), 
('Helen', 'Bradley', '1942-11-28', 2, 1, NULL,'F'), 
('Jim', 'Smith', '1953-02-10', 2, 1, NULL,'M'), 
('Stephen', 'Smith', '1957-01-13', 2, 1, '2005-05-25','M'), 
('Daniel', 'Smith', '1961-11-28', 2, 1, NULL,'M'), 
('Michelle', 'Smith', '1963-07-02', NULL, NULL, NULL,'F'), 
('Anne', 'Smith', '1958-04-22', NULL, NULL, NULL,'F'), 
('Josh', 'Smith', '1990-01-28', 8, 7, NULL,'M'), 
('Stephanie', 'Smith', '1992-05-18', 8, 7, NULL,'F'), 
('Rachel', 'Smith', '1996-11-05', 8, 7, NULL,'F'), 
('Reg', 'Howard', '1949-07-07', NULL, NULL, NULL,'M'), 
('Richard', 'Howard', '1972-12-26', 3, 13, NULL,'M'), 
('Phillip', 'Howard', '1975-06-01', 3, 13, NULL,'M'), 
('Robert', 'Bradley', '1939-03-07', NULL, NULL, NULL,'M'), 
('Matthew', 'Bradley', '1964-10-26', 4, 16, '2001-04-27','M'), 
('Yvonne', 'Bradley', '1966-11-28', 4, 16, NULL,'F'), 
('James', 'Bradley', '1971-01-26', 4, 16, NULL,'M'), 
('Anna', 'Reuper', '1918-01-27', NULL, NULL, NULL,'F'), 
('Ludwig', 'Reuper', '1923-07-01', NULL, NULL, '2001-07-01','M'), 
('Heinz', 'Reuper', '1965-01-28', 20, 21, NULL,'M'), 
('Veronica', 'Reuper', '1959-04-01', 20, 21, NULL,'F'), 
('Marco', 'Johnson', '1958-09-04', NULL, NULL, NULL,'M'), 
('Francesca', 'Reuper', '1990-11-01', 23, 24, NULL,'F'), 
('Lou', 'Jung', '1940-02-03', NULL, NULL, NULL,'M'), 
('Tammi', 'Sinclair', '1971-02-03', NULL, NULL, NULL,'F'), 
('Lori', 'Navarro', '1973-12-15', NULL, NULL, NULL,'F'), 
('Kattie', 'Paine', '1980-10-31', NULL, NULL, NULL,'F'); 


INSERT INTO couple (alphaSpouse,omegaSpouse, coupleStart, coupleEnd) VALUES 
(1,2,'1940-05-22', NULL), 
(3,13,'1969-07-30', '1973-10-01'), 
(3,26,'1980-01-10', '1982-12-01'), 
(4,16,'1963-04-05', NULL), 
(6,9,'1979-06-21', NULL), 
(7,8,'1987-09-14', NULL), 
(20,21,'1936-10-26', NULL), 
(23,24,'1988-05-01', '1997-07-01'), 
(19,27,'1992-10-31', '1993-01-31'), 
(19,28,'1995-08-18', '1997-04-27'), 
(19,29,'2015-09-19', NULL); 

Я пытаюсь перечислить всех людей, у которых есть внуки и сколько внуков у них есть. Мне бы хотелось, чтобы это было так; Как вывести рекурсивные (родители -> дети -> внуки)

Я попытался сделать это ниже, но я застрял, пытаясь СЧИТАТЬ grandkids вне подзапроса WHERE .. был ли я даже на правильном пути?

SELECT grandp.persFName + ' ' + grandp.persLName, COUNT(grandkids.persID) 
FROM person grandp 
JOIN person child ON grandp.persID = child.motherID OR grandp.persID = child.fatherID 
WHERE child.persID IN (SELECT grandkids.motherID 
         FROM person grandkids 
         union 
         SELECT grandkids.fatherID 
         FROM person grandkids) 
GROUP BY grandp.persFName + ' ' + grandp.persLName 
+2

Вы можете разместить некоторые данные? –

+0

Извините, что я забыл, я просто добавил – Calisto

ответ

2

Когда у вас есть иерархические данные, подобные вашим, лучше всего использовать общие выражения таблиц. Это позволит вам построить иерархические данные в форме, которую вы можете использовать позже - в вашем примере, чтобы сосчитать внуков. Вы можете использовать построение данных по уровням или расстоянию от корня.

with temp (persid, ancestorid, level) as (
    select persid, persid as ancestorid, 0 as level 
    from person 
    where motherid is null and fatherid is null 

    union all 

    select person.persid, temp.ancestorid, temp.level + 1 as level 
    from person 
    inner join temp on temp.persid = person.motherid or temp.persid = person.fatherid 
) 

select temp.ancestorid as persid, 
    person.persFName + ' ' + person.persLName as name, 
    count(*) 
from temp 
inner join person 
on temp.ancestorid = person.persid 
where level = 2 
group by temp.ancestorid, person.persFName, person.persLName 

Запрос строит КТР каждого человека, это предок и уровень (0 = деды, 2 = внуки). Затем вы можете легко сосчитать внуков для каждого предка.

SQL Скрипка: http://sqlfiddle.com/#!3/99c97/2

(Примечание: Я оставила пару таблицы, как это здесь не требуется).

1

Попробуйте это я просто использовал обычные выражения таблицы рекурсивно, чтобы получить результат

;WITH Allpersons AS 
(
SELECT persID AS Id 
,persFName+' '+persLName AS Name 
,fatherID 
,motherID 
FROM PERSON 

) 
SELECT 
GrandFatherCTE.Name 
,COUNT(GrandFatherCTE.Id) AS CountOfChild 
FROM Allpersons AllPersonsCTE 
INNER JOIN 
Allpersons ParentsCte 
ON 
AllPersonsCTE.fatherID = ParentsCte.Id 
OR 
AllPersonsCTE.motherID = ParentsCte.Id 
INNER JOIN 
Allpersons GrandFatherCTE 
ON 
ParentsCte.fatherID = GrandFatherCTE.Id 
OR 
ParentsCte.motherID = GrandFatherCTE.Id 
INNER JOIN 
COUPLE 
ON 
GrandFatherCTE.Id = COUPLE.alphaSpouse 
OR 
GrandFatherCTE.Id = COUPLE.omegaSpouse 

GROUP BY 
GrandFatherCTE.Name 
,COUPLE.coupleID 
ORDER BY 
CountOfChild ASC 
,COUPLE.coupleID ASC 
Смежные вопросы