+1  A: 

why not use an additional table relating Contacts and UserGroups? e.g.

ContactsAccess

int UserGroups.Id (FK)
int Contacts.Id (FK)

You could use a special value (e.g. zero (0)) to indicate unrestricted access ,or you could modify the Contacts table to indicate the permission type.

Jonathan Fingland
It may also just be 4 individuals from "Users" and 2 groups. That would mean another relation table between Users and Contacts right?That is going to be really expensive on data retrieval :(
Alex
if it requires Users as well, then I would say an additional table is the right choice.
Jonathan Fingland
A: 

The way I'd probably go about it is a table similar to the following (MySQL):

CREATE TABLE `ContactsVisibleTo` (
    `ContactID` INT NOT NULL ,
    `Type` ENUM( 'User', 'Group' ) NOT NULL ,
    `ID` INT NOT NULL
)

A unique or primary key over all three fields probably isn't a bad idea either. The switch between public/private should be a field in the Contacts table.

Matthew Scharley
joins to this table would still have to be doubled (on type='Contact'... and on type='Group') only it has the disadvantage of making the table itself larger. A two table approach has the same number of joins, but smaller tables, and the ability to use foreign key constraints.
Jonathan Fingland