In this example, there's what looks like a bug - see remarks at end of code: * Create two records for each person, for role as . * parent and role as child . * (Since the data is in raw form, it could be in an . * INPUT PROGRAM, and I could write two records for . * one more easily, and without an intermediate file. * By an anomaly of implementation, an INPUT PROGRAM . * cannot contain a GET, ADD and MATCH FILES.) . STRING ROLE (A01) /FAMILY(A10). LOOP #ROLE = 1 To 2. . DO IF #ROLE EQ 1 /* 1 = Parent role */. . COMPUTE ROLE = 'P' /* 'P' = Parent */. . COMPUTE FAMILY = SUBJECT. . ELSE IF #ROLE EQ 2 /* 2 = Child role */. . DO IF PARENT EQ '99999'. . COMPUTE ROLE = ' ' /* ' ' = Never a child */. . ELSE. . COMPUTE ROLE = 'C' /* 'C' = Child */. . COMPUTE FAMILY = PARENT. . END IF. . END IF. . DO IF ROLE NE ' ' /* Skip never-children */. . XSAVE OUTFILE=Fam_Memb /KEEP=ROLE FAMILY ALL. . END IF. END LOOP. EXECUTE /* Here, it really is needed */. GET FILE = Fam_Memb. SORT CASES BY FAMILY ROLE. . /**/ LIST. STRING CHILD01 TO CHILD05(A10) /* Allow for 5 children */. VECTOR CHILDREN = CHILD01 TO CHILD05. DO IF FAMILY NE LAG(FAMILY). . COMPUTE #KIDNUM = 1. ELSE. . COMPUTE #KIDNUM = #KIDNUM + 1. . DO REPEAT CHILD = CHILD01 TO CHILD05. . COMPUTE CHILD = LAG(CHILD). . END REPEAT. END IF. IF ROLE NE 'P' /* So parents aren't their own children */ CHILDREN(#KIDNUM) = SUBJECT. TEMPORARY. STRING SPACER(A20). LIST ROLE TO BRTHDATE SPACER CHILD01 TO CHILD05. [output skipped] * Get rid of the children; we don't need them anymore . SELECT IF ROLE EQ 'P'. * And get rid of variables no longer needed . ADD FILES /FILE=* /DROP=ROLE FAMILY. TEMPORARY. STRING SPACER(A32). LIST PARENT TO BRTHDATE SPACER CHILD01 TO CHILD05. List |---------------------------|-----------------------| |Output Created |08 Nov 05 21:39:45 | |---------------------------|-----------------------| The variables are listed in the following order: LINE 1: PARENT SUBJECT BRTHDATE SPACER LINE 2: CHILD01 CHILD02 CHILD03 CHILD04 CHILD05 Line 1: PARENT SUBJECT BRTHDATE PARENT: 99999 Antony 19271010 CHILD01: Frank PARENT: 99999 Eugene 19441216 CHILD01: PARENT: Antony Frank 19460701 CHILD01: Mike Patricia PARENT: Maria Katrina 19520927 CHILD01: PARENT: 99999 Maria 19330803 CHILD01: Vincent Paul Katrina PARENT: Frank Mike 19720327 CHILD01: PARENT: Frank Patricia 19680216 CHILD01: PARENT: Maria Paul 19540123 CHILD01: PARENT: Maria Vincent 19500606 CHILD01: Number of cases read: 9 Number of cases listed: 9 ...................................................... Concerning the apparent problem: DO IF FAMILY NE LAG(FAMILY). . COMPUTE #KIDNUM = 1. ELSE. . COMPUTE #KIDNUM = #KIDNUM + 1. . DO REPEAT CHILD = CHILD01 TO CHILD05. . COMPUTE CHILD = LAG(CHILD). . END REPEAT. END IF. This looks like it shouldn't work for the first case, where "FAMILY NE LAG(FAMILY)" should test 'missing', the whole construct skipped, and #KIDNUM not be set at all. It works because "FAMILY" is a string variable. LAG of a string, for the first case, is blank, not missing, since there's no system-missing for strings. Blank tests not-equal to the first family name, which isn't blank. So, don't change it. But standard logic for the conditional, which would work with numbers, would be, DO IF MISSING(LAG(FAMILY). . COMPUTE #KIDNUM = 1. ELSE IF FAMILY NE LAG(FAMILY). . COMPUTE #KIDNUM = 1. ELSE. . COMPUTE #KIDNUM = #KIDNUM + 1. . DO REPEAT CHILD = CHILD01 TO CHILD05. . COMPUTE CHILD = LAG(CHILD). . END REPEAT. END IF.