I think you misunderstood me on the duplicates. I'm talking about how easy it is to e.g. left join an attribute from another table and under-qualify the association so that you accidentally pull in unwanted rows. It's not that you have duplicates in the data; the data is correct and the model is correct. It's rather that the query is incorrect and the set of tests, owing to them typically being written by the same person who wrote the code, doesn't populate the association table with more rows than expected.
I mention this because it's a bug I've seen crop up several times in production. When you write 'join' you're typically fetching data to add extra columns to your result set; it's relatively unusual to want a row product in the absence of group by & aggregates, or an ORM doing eager loading of a detail table. But nothing in SQL requires you to state your product expectations on the join, apart from left/right outer vs inner join. I personally think SQL could do with forcing people to be more explicit on this point.
I fully agree on the inconsistencies in NoSQL; I think the most sensible way to use NoSQL is as a document store without relations, and keep the relations somewhere else. Manually maintaining invariants (especially of the denormalized bidirectional kind that some stores require) in an environment with less than complete transaction support isn't my idea of fun.