Wordpress - What's the difference between term_id and term_taxonomy_id

If you take a look into the Wordpress documentation you will find Wordpress Taxonomies

  • term_id is the ID of a term in the terms table
  • term_taxonomy_id is a unique ID for the term + taxonomy pair.

The Codex says:

  • term_id is the ID of a term in the terms table
  • term_taxonomy_id is a unique ID for the term+taxonomy pair

What does this mean?

A term is a word. It can belong to a taxonomy, such as tags, categories, or a custom taxonomy. The thing is: there can be several taxonomies containing the same term.

Let’s say you have a term called “fattening“. This word has an id number. This is the term_id. It doesn’t depend on how this word is used, i.e. in which taxonomies the term appears.

Now the word “fattening” as a post tag also has a number. This is the term_taxonomy_id. It corresponds to “the post tag ‘fattening’“.

Maybe you also have a category called “fattening”. While the term_id is the same, the term_taxonomy_id for “the category ‘fattening’” is different.


As this is a part of a bigger understanding of the design I will describe it as whole... :)

In WP 4.5.3 there are still all these tables (I will talk about them without prefix):

  • posts
  • term_relationships
  • term_taxonomy
  • terms

The path to get post terms' readable names goes through them all.

posts
the main identificator here is ID - an id of a post (of any type)

term_relationships
stores pairs of:
object_id - can be posts.ID (but does not have to be)
term_taxonomy_id - this is NOT id of a term (category) but an id of RELATIONSHIP between a term(category) and taxonomy("category type")

term_taxonomy
the main identificator here is term_taxonomy_id desribed above ^^
another important columns:
term_id - an id of a term (category)
taxonomy - stores the term's taxonomy("category type")

This one might seem funny, but the initial intend was to add the ability for terms to have more taxonomies (which in some cases can make sense).

terms
the main identificator here is the term_id - an id of an category
another important columns here are:
name - readable category name e.g. "Music Genres"
slug - the slug of a term usable e.g. in URL

So the brutal demonstrating SQL to
get all published posts and all their categories with categories' names
could look like this (add prefixes to tables when testing on your own WP DB):

SELECT * FROM
posts #gets posts
LEFT JOIN
term_relationships #gets posts relationships to term_taxonomies
ON(posts.ID=term_relationships.object_id)
LEFT JOIN
term_taxonomy #gets term_ids 
ON(term_relationships.term_taxonomy_id=term_taxonomy.term_taxonomy_id)
LEFT JOIN
terms #finally, gets terms' names
ON(term_taxonomy.term_id=terms.term_id)
WHERE (
    (posts.post_status='publish') 
    #optionally you can filter by a certain post_type:
    #AND
    #(posts.post_type='some_post_type')
)
ORDER BY posts.ID ASC