Esri provides a good resource: Joining the attributes from a table
What you need to do is peform a one-to-many join versus the one-to-one join. The issue you are running into with your data is that you have multiple rows in your table that share the same ID. When you perform a one-to-one join the first entry will be joined and the other rows with the same ID get "dropped". However when you have a one-to-many join then those similar ID are all joined to the same ID in your shapefile. Below provides more details and illustrations.
Joining the attributes from a table
Typically, you'll join a table of data to a layer based on the value of a field that can be found in both tables. The name of the field does not have to be the same, but the data type has to be the same; you join numbers to numbers, strings to strings, and so on. You can perform a join with either the Join Data dialog box, accessed by right-clicking a layer in ArcMap, or the Add Join tool.
One-to-one and many-to-one relationships
When you join tables in ArcMap, you establish a one-to-one or many-to-one relationship between the layer's attribute table and the table containing the information you want to join. The example below illustrates a one-to-one relationship between each county and that county's population change data. In other words, there's one population change for each county.
One-to-many and many-to-many relationships
When using data where a one-to-many or many-to-many relationship exists, you should use a relate or relationship class to establish the relationship between the datasets. However, it is possible to create a join under these circumstances. When you create a join in such a case, there are differences between how tools and other layer-specific settings work depending on the data source. If you are using geodatabase data to create the join, all matching records are returned. If you are using nondatabase data, like shapefiles or dBASE tables, to create the join, only the first matching record is returned.
This means that if you have created a 1:M or M:M join with geodatabase data and you generate a report, you see multiple records in the report, one for each corresponding match. The multiple matches are also seen when using a join field while symbolizing a joined layer, labeling, identifying features, generating a graph, and using either the Find or Hyperlink tool. If you are using the joined layer as input to a geoprocessing tool or in an export operation, the multiple matching records are used.
View table and can reference this as an alternative as well How To: Create a one-to-many join in ArcMap
Instructions provided describe how to create a table with a one-to-many mapping to another table.
Add a field to the attribute table and calculate it as Township+Lot+Concession using Field Calculator, do the same in the csv and then join on this field.
Or if you want to complicate things you can also use some Python code. I create a dictionary from the csv file and use this to update fields in the attribute table. You will need to adjust the indexing to match the columns in the csv file, see comment below:
import arcpy
csvfile = r'C:\Test\csvfile.csv' #Change to match your data
fc = r'C:\filegeodatabase.gdb\feature_class' #Change to match your data
d = {} #Create empty dictionary
#Read the lines of the csvfile and and to dictionary
with open(csvfile,'r') as f:
f.readline() # skip header line
for line in f:
row=line.split(',') #Change , to what delimits the fields
#You might need to adjust indexing on the following row to match the columns of the csv file:
d[row[0]+row[1]+row[2]]=[row[3],row[4],row[5]]
with arcpy.da.UpdateCursor(fc,['TOWNSHIP','CONCESSION','LOT','LAST_NAME','FIRST_NAME','PPA']) as cursor:
for row in cursor:
try:
row[3],row[4],row[5]=d[row[0]+row[1]+row[2]]
cursor.updateRow(row)
except:
print '{0} {1} {2} was not found in the csvfile'.format(*list(row[3],row[4],row[5]))
Example of indexing:
Best Answer
It didn't work because while saving it defaulted to a CSV UTF-8 file type instead of a normal CSV file type. Once I changed to regular CSV file type, it worked just fine.