I think a lot depends on what information you are trying to store and be able to retrieve from the database. Attempting to second-guess this, I’d propose the following set of tables (and note that only the one column in any of these tables allow nulls):
-- User -----
user_id (primary key)
name
-- Bike ------
bike_id (primary key)
description
current_owner nullable (foreign key to User)
This presumes that “bike ownership” is a criticial and frequently desired piece of information, and is worth adding denormalized data to the structure to make finding a bike’s current user or a user’s current bikes trivial. (A key reason for adding denormalized data is to simplify data retrieval and/or improve performance. Skipping working out sales history on every query you make does both.) If duration of ownership is important, a column for “purchased_on” could be added, or you delve into the transaction tables.
To track when bikes were purchased:
-- Bike_Purchase ------
user_id (foreign key to User)
bike_id (foreign key to Bike)
purchased_on
(primary key on all three columns)
would track every time a user purchased a bike. If instead you’d rather track when a bike was sold, you could have
-- Bike_Sale ------
user_id (foreign key to User)
bike_id (foreign key to Bike)
sold_on
(primary key on all three columns)
To track both purchases and sales, include either both tables or a simple conglomerate:
-- Bike_Transaction ------
user_id (foreign key to User)
bike_id (foreign key to Bike)
transaction_type **
transaction_date
(primary key on all four columns)
This allows you to accurately track purchases and sales for your users, and disregard transactions by non-users. Sold a bike? Make an entry. Don’t know or care who they sold it to? Don’t make an entry.
Whichever time-tracking table you use, determining duration of ownership is as simple as joining on (user_id, bike_id) and getting max(date). Piecing together the “ownership chain” of a given bike, or what bikes a user owned and when/for how long would be tricky, but entirely doable.
** For transaction_type, you may need to set up a Transaction_Type table to track the different transactions (sold, purchased, traded, found, lost/stolen, etc. etc.) Alternatively, you could make it a varchar containing a descriptive string, or put a CHECK constraint to limit it to selected values.