Please consider this as an alternative. The previous two examples will both require that you make changes to the schema as the application's scope grows in addition the "custom_column" solution is difficult to extend and maintain. Eventually you'll end up with Custom_510 and then just imagine how awful this table will be to work with.
First let's use your Companies schema.
[Companies] ComnpanyId, COMPANY_NAME, CREATED_ON
Next we'll also use your Users schema for top level required attributes that will be used/shared by all companies.
[Users] UserId, COMPANY_ID, FIRST_NAME, LAST_NAME, EMAIL, CREATED_ON
Next we build a table where we will define our dynamic attributes that are specific to each companies custom user attributes. So here an example value of the Attribute column would be "LikeMusic":
[UserAttributeDefinition] UserAttributeDefinitionId, CompanyId, Attribute
Next we define a UserAttributes table that will hold user attribute values
[UserAttributes] UserAttributeDefinitionId, UserId, Value
This can be modified in many ways to be better for performance. You can use multiple tables for UserAttributes making each one specific to the data type being stored in Value or just leave it as a VarChar and work with it as a keyvalue store.
You also may want to move CompanyId off of the UserAttributeDefiniton table and into a cross reference table for future proofing.
I usually go with the multiple table approach.
You might find however, that in terms of read/write performance your current single table format outperforms both alternatives.
XML columns for structured data in a relational database are, I think, trying to do the same job as tables and columns. Before you head down that route, consider the problems you may encounter when in the future you need to change the format of the data.
Best Answer
Its actually a simple descision based on how often you update the project threshold vs. how often you query the samples.
If the project level threshold is not updated very often then I would copy the threshold to every sample row (with perhaps an extra column to indicate an overridden value). This will make any queries simpler and faster.
On the other hand if you update the default threshold frequently. The keep it at the project level and take the (slight) performance hit for the join for every query.