Ahora que tengo un par de minutos, puedo ampliar mi comentario anterior. ST_Union() en PostGIS y el Unión en QGIS hacen cosas diferentes, a pesar de los nombres similares. ST_Union() es similar a la herramienta Disolver en QGIS, ya que eliminará los límites de las características adyacentes y/o agrupará las características individuales con los mismos valores de atributos en características Multi*.
Creo que lo que está buscando es el ST_Intersection() de las geometrías superpuestas.
Para hacer las cosas más confusas, creo que querrás usar el operador de PostgreSQL UNION que añadirá las geometrías seleccionadas y otros atributos de las dos tablas en la misma columna.
Así que creo que la respuesta que buscas es algo así (actualizado para responder con más precisión a tu pregunta original y a tu comentario posterior):
WITH cte as (
SELECT nsg, NULL as ffh, ST_Area(geom) as area, geom
FROM p_gaiac.shape1
UNION
SELECT NULL as nsg, ffh, ST_Area(geom) as area, geom
FROM p_gaiac.shape2
UNION
SELECT nsg, ffh, area, geom
FROM (SELECT nsg, ffh, ST_Area(ST_Intersection(a.geom, b.geom)) as area,
ST_Intersection(a.geom, b.geom) as geom
FROM p_gaiac.shape1 as a
JOIN p_gaiac.shape2 as b ON ST_Intersects(a.geom, b.geom)) c
)
SELECT ROW_NUMBER () OVER () as new_id, nsg, ffh, area, geom
from cte;
Al colocar la consulta principal dentro de un CTE A continuación, puede asignar un nuevo ID único a todo el conjunto, que le permitirá llevarlo a QGIS para visualizarlo. Colocando marcadores de posición NULL en las columnas para las que la tabla original no tiene, podrá entonces rellenar ambas columnas en la tercera sentencia select, que querrá para las áreas superpuestas. Puede ampliar esto para incluir más columnas de sus tablas originales según sea necesario, utilizando el marcador de posición NULL.