Calculating overlap between groups
First, we need to get a list of all buckets. if you already have a table buckets with all bucket_id (as PK), this part is not needed:

with 
  buckets (bucket_id) as
  ( select distinct bucket_id
    from table_x
  ) ,


Then we get all bucket couples and the count of their common items - through a self-join:

  couples (bucket_a, bucket_b, cnt) as 
    ( select a.bucket_id, b.bucket_id, count(*)
      from table_x a 
        join table_x b
          on  a.bucket_id &lt;= b.bucket_id
          and a.item_id = b.item_d 
      group by a.bucket_id, b.bucket_id
    )


Then we can show our results:

select a.bucket_id      as bucket_a, 
       b.bucket_id      as bucket_b, 
       coalesce(cnt, 0) as common_items
from buckets a
  join buckets b
    on a.bucket_id &lt;= b.bucket_id
  left join couples c
    on  a.bucket_id = c.bucket_a
    and b.bucket_id = c.bucket_b ;


The above will show, for your sample table:

bucket_a  bucket_b  common_items
================================
A         A         2
A         B         1
A         C         2
A         D         0
B         B         2
B         C         1
B         D         1
C         C         3
C         D         0
D         D         1


If you want the pivoted output, you'll need one more processing.



If the number of buckets is very low as you say, you may try this one as well:

with 
  buckets (bucket_id) as
  ( select distinct bucket_id
    from table_x
  ) ,
select a.bucket_id      as bucket_a, 
       b.bucket_id      as bucket_b,
       ( select count(*)
         from table_x aa
           join table_x bb
             on  aa.item_id = bb.item_d 
         where a.bucket_id = aa.bucket_id
           and b.bucket_id = bb.bucket_id
       ) as common_items
from buckets a
  join buckets b
    on a.bucket_id &lt;= b.bucket_id ;