A fairly normalized design would look something like:
Location(addr_id,primary_contact_id, street_addr, city, post_code, country)
Contact(contact_id,first_name, last_name, title);
LivesAt(contact_id,addr_id)
MarriedTo(contact_id_1,contact_id_2)
ChildOf(parent_id,child_id)
These would basically be your tables. Then you could create views:
1.Family. Assume a family is at least one parent and a child living at the same address, and they share the same surname (in the case of a parent and child having different surnames, you will address the letter to them both by their full names).
CREATE VIEW Family AS
SELECT UNIQUE last_name, addr_id, street_addr, city, post_code, country FROM
(SELECT p1.contact_id, p1.first_name, p1.last_name FROM Contact AS p1)
INNER JOIN
(SELECT p2.contact_id, p2.first_name, p2.last_name FROM Contact AS p2)
ON (p2.last_name = p1.last_name AND p2.contact_id IN ChildOf
AND p1.contact_id IN ChildOf)
INNER JOIN
Location AS l
ON (p1.contact_id = l.primary_contact_id)
OR (p2.contact_id = l.primary_contact_id)
Format as you see fit.
2.Married couples with no children.
CREATE VIEW Couple AS
SELECT * FROM
(SELECT C.contact_id, C.last_name, C.title FROM Contact AS C
INNER JOIN MarriedTo AS M
ON (M.contact_id_1=C.contact_id)
INNER JOIN
SELECT D.contact_id, D.last_name, D.title FROM Contact as D
ON (M.contact_id_2=D.contact_id)
INNER JOIN Location AS L
ON
L.addr_id NOT IN Family
AND (L.primary_contact_id = M.contact_id_1)
OR (L.primary_contact_id = M.contact_id_2)
And so on.