If A is the key in fish , any projection only onto the fish will create a result set where A is still unique.
A join between tabular fish and any table with a 1: 1 ratio (for example, fish_type) will create a result set where A is unique.
Joining another table that has a 1: M or M: M relationship from fish (for example, fish_beits) will NOT produce a result where A is unique unless you provide a filter predicate on the "other" side (for example, bait='Dynamite' ).
SELECT * FROM (SELECT * FROM FISH) D, (SELECT * FROM FISH2) E WHERE DA = EA
... is logically equivalent to the following statement, and most databases (including MySQL) will perform the conversion:
select * from fish join fish2 on(fish.a = fish2.a)
Whether A is unique in the result set depends on the key fish2 and their relationship (see above).
Concatenation does not preserve uniqueness. Consider the following case:
concat("10", "10") => "1010" concat("101", "0") => "1010"
Therefore, your final request ...
SELECT * FROM (SELECT CONCAT(A,B) AS DUCK, C FROM FISH) D ,(SELECT CONCAT(A,B) AS DUCK2, C FROM FISH2) E WHERE D.DUCK = E.DUCK2
... will not (necessarily) produce the same result as
select * from fish join fish2 on( fish.a = fish2.a and fish.b = fish2.b )
I wrote necessarily, because collisions depend on actual values. Some time ago I was looking for a mistake when the root cause was just that. The code worked several years before the error showed up.