create cursor headerCursor ( myID I, myLabel C(20) ) INSERT INTO headerCursor (myID, myLabel) VALUES ( 1, "First Record" ) INSERT INTO headerCursor (myID, myLabel) VALUES ( 2, "Second Record" ) INSERT INTO headerCursor (myID, myLabel) VALUES ( 3, "Third Record" ) INSERT INTO headerCursor (myID, myLabel) VALUES ( 4, "Fourth Record" ) INSERT INTO headerCursor (myID, myLabel) VALUES ( 5, "Fifth Record" ) create cursor detailCursor( myID I, dtlLabel C(20), dtlValue C(20) ) INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 1, "COLOR", "RED") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 1, "BIRTHDATE", "04/13/1976") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 1, "SPEED", "123") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 1, "VISIBLE", ".F.") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 1, "ORIGIN", "SPACE") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 2, "VALUE", "0") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 2, "TEXT", "0") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 2, "VISIBLE", ".T.") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 3, "MOVABLE", ".F.") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 3, "COLOR", "GREEN") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 4, "COLOR", "BLACK") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 4, "VISIBLE", ".T.") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 4, "VALUE", "10") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 4, "TEXT", "TEN") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 4, "MOVABLE", ".T.") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 5, "SPEED", "500") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 5, "BIRTHDATE", "08/08/1980") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 5, "COLOR", "WHITE") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 5, "VALUE", "37") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 5, "ORIGIN", "BOONDOCKS") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 5, "VISIBLE", ".T.") INSERT INTO detailCursor( myID, dtlLabel, dtlValue ) VALUES ( 5, "MOVABLE", ".F.") select distinct dtlLabel from detailCursor into cursor attList nofilter order by dtlLabel cFieldList = "" cJoinStatement = "" select attList go top in attList scan cFieldList = cFieldList + iif(!empty(cFieldList), ",", "") + ; "iif(isNull(" + alltrim(attList.dtlLabel) + "alias.dtlValue), SPACE(20)," + ; alltrim(attList.dtlLabel) + "alias.dtlValue) as " + alltrim(attList.dtlLabel) cJoinStatement = cJoinStatement + ; " LEFT OUTER JOIN detailCursor " + alltrim(attList.dtlLabel) + "alias ON headerCursor.myID = " + ; alltrim(attList.dtlLabel) + "alias.myID and " + alltrim(attList.dtlLabel) + "alias.dtlLabel = '" + alltrim(attList.dtlLabel) + "' " endscan select headerCursor.*, &cFieldList ; from headerCursor &cJoinStatement>We have some transaction tables that are not properly normalized, with transaction records containing some detail fields right in it. I know this is against good practice but 13 years ago it seemed like a good trade-off to gain speed, plus we had few detail types back then. With this structure it is easy to derive cursors that have all fields of interest in one record and reports can show all fields in one line very naturally and speedily.