== Physical Plan ==
* HashAggregate (29)
+- Exchange (28)
   +- * HashAggregate (27)
      +- * Project (26)
         +- SortMergeJoin FullOuter (25)
            :- * Sort (14)
            :  +- * HashAggregate (13)
            :     +- Exchange (12)
            :        +- * HashAggregate (11)
            :           +- * Project (10)
            :              +- * BroadcastHashJoin Inner BuildRight (9)
            :                 :- * Filter (3)
            :                 :  +- * ColumnarToRow (2)
            :                 :     +- Scan parquet default.store_sales (1)
            :                 +- BroadcastExchange (8)
            :                    +- * Project (7)
            :                       +- * Filter (6)
            :                          +- * ColumnarToRow (5)
            :                             +- Scan parquet default.date_dim (4)
            +- * Sort (24)
               +- * HashAggregate (23)
                  +- Exchange (22)
                     +- * HashAggregate (21)
                        +- * Project (20)
                           +- * BroadcastHashJoin Inner BuildRight (19)
                              :- * Filter (17)
                              :  +- * ColumnarToRow (16)
                              :     +- Scan parquet default.catalog_sales (15)
                              +- ReusedExchange (18)


(1) Scan parquet default.store_sales
Output [3]: [ss_sold_date_sk#1, ss_item_sk#2, ss_customer_sk#3]
Batched: true
Location [not included in comparison]/{warehouse_dir}/store_sales]
PushedFilters: [IsNotNull(ss_sold_date_sk)]
ReadSchema: struct<ss_sold_date_sk:int,ss_item_sk:int,ss_customer_sk:int>

(2) ColumnarToRow [codegen id : 2]
Input [3]: [ss_sold_date_sk#1, ss_item_sk#2, ss_customer_sk#3]

(3) Filter [codegen id : 2]
Input [3]: [ss_sold_date_sk#1, ss_item_sk#2, ss_customer_sk#3]
Condition : isnotnull(ss_sold_date_sk#1)

(4) Scan parquet default.date_dim
Output [2]: [d_date_sk#4, d_month_seq#5]
Batched: true
Location [not included in comparison]/{warehouse_dir}/date_dim]
PushedFilters: [IsNotNull(d_month_seq), GreaterThanOrEqual(d_month_seq,1200), LessThanOrEqual(d_month_seq,1211), IsNotNull(d_date_sk)]
ReadSchema: struct<d_date_sk:int,d_month_seq:int>

(5) ColumnarToRow [codegen id : 1]
Input [2]: [d_date_sk#4, d_month_seq#5]

(6) Filter [codegen id : 1]
Input [2]: [d_date_sk#4, d_month_seq#5]
Condition : (((isnotnull(d_month_seq#5) AND (d_month_seq#5 >= 1200)) AND (d_month_seq#5 <= 1211)) AND isnotnull(d_date_sk#4))

(7) Project [codegen id : 1]
Output [1]: [d_date_sk#4]
Input [2]: [d_date_sk#4, d_month_seq#5]

(8) BroadcastExchange
Input [1]: [d_date_sk#4]
Arguments: HashedRelationBroadcastMode(List(cast(input[0, int, true] as bigint)),false), [id=#6]

(9) BroadcastHashJoin [codegen id : 2]
Left keys [1]: [ss_sold_date_sk#1]
Right keys [1]: [d_date_sk#4]
Join condition: None

(10) Project [codegen id : 2]
Output [2]: [ss_item_sk#2, ss_customer_sk#3]
Input [4]: [ss_sold_date_sk#1, ss_item_sk#2, ss_customer_sk#3, d_date_sk#4]

(11) HashAggregate [codegen id : 2]
Input [2]: [ss_item_sk#2, ss_customer_sk#3]
Keys [2]: [ss_customer_sk#3, ss_item_sk#2]
Functions: []
Aggregate Attributes: []
Results [2]: [ss_customer_sk#3, ss_item_sk#2]

(12) Exchange
Input [2]: [ss_customer_sk#3, ss_item_sk#2]
Arguments: hashpartitioning(ss_customer_sk#3, ss_item_sk#2, 5), true, [id=#7]

(13) HashAggregate [codegen id : 3]
Input [2]: [ss_customer_sk#3, ss_item_sk#2]
Keys [2]: [ss_customer_sk#3, ss_item_sk#2]
Functions: []
Aggregate Attributes: []
Results [2]: [ss_customer_sk#3 AS customer_sk#8, ss_item_sk#2 AS item_sk#9]

(14) Sort [codegen id : 3]
Input [2]: [customer_sk#8, item_sk#9]
Arguments: [customer_sk#8 ASC NULLS FIRST, item_sk#9 ASC NULLS FIRST], false, 0

(15) Scan parquet default.catalog_sales
Output [3]: [cs_sold_date_sk#10, cs_bill_customer_sk#11, cs_item_sk#12]
Batched: true
Location [not included in comparison]/{warehouse_dir}/catalog_sales]
PushedFilters: [IsNotNull(cs_sold_date_sk)]
ReadSchema: struct<cs_sold_date_sk:int,cs_bill_customer_sk:int,cs_item_sk:int>

(16) ColumnarToRow [codegen id : 5]
Input [3]: [cs_sold_date_sk#10, cs_bill_customer_sk#11, cs_item_sk#12]

(17) Filter [codegen id : 5]
Input [3]: [cs_sold_date_sk#10, cs_bill_customer_sk#11, cs_item_sk#12]
Condition : isnotnull(cs_sold_date_sk#10)

(18) ReusedExchange [Reuses operator id: 8]
Output [1]: [d_date_sk#4]

(19) BroadcastHashJoin [codegen id : 5]
Left keys [1]: [cs_sold_date_sk#10]
Right keys [1]: [d_date_sk#4]
Join condition: None

(20) Project [codegen id : 5]
Output [2]: [cs_bill_customer_sk#11, cs_item_sk#12]
Input [4]: [cs_sold_date_sk#10, cs_bill_customer_sk#11, cs_item_sk#12, d_date_sk#4]

(21) HashAggregate [codegen id : 5]
Input [2]: [cs_bill_customer_sk#11, cs_item_sk#12]
Keys [2]: [cs_bill_customer_sk#11, cs_item_sk#12]
Functions: []
Aggregate Attributes: []
Results [2]: [cs_bill_customer_sk#11, cs_item_sk#12]

(22) Exchange
Input [2]: [cs_bill_customer_sk#11, cs_item_sk#12]
Arguments: hashpartitioning(cs_bill_customer_sk#11, cs_item_sk#12, 5), true, [id=#13]

(23) HashAggregate [codegen id : 6]
Input [2]: [cs_bill_customer_sk#11, cs_item_sk#12]
Keys [2]: [cs_bill_customer_sk#11, cs_item_sk#12]
Functions: []
Aggregate Attributes: []
Results [2]: [cs_bill_customer_sk#11 AS customer_sk#14, cs_item_sk#12 AS item_sk#15]

(24) Sort [codegen id : 6]
Input [2]: [customer_sk#14, item_sk#15]
Arguments: [customer_sk#14 ASC NULLS FIRST, item_sk#15 ASC NULLS FIRST], false, 0

(25) SortMergeJoin
Left keys [2]: [customer_sk#8, item_sk#9]
Right keys [2]: [customer_sk#14, item_sk#15]
Join condition: None

(26) Project [codegen id : 7]
Output [2]: [customer_sk#8, customer_sk#14]
Input [4]: [customer_sk#8, item_sk#9, customer_sk#14, item_sk#15]

(27) HashAggregate [codegen id : 7]
Input [2]: [customer_sk#8, customer_sk#14]
Keys: []
Functions [3]: [partial_sum(cast(CASE WHEN (isnotnull(customer_sk#8) AND isnull(customer_sk#14)) THEN 1 ELSE 0 END as bigint)), partial_sum(cast(CASE WHEN (isnull(customer_sk#8) AND isnotnull(customer_sk#14)) THEN 1 ELSE 0 END as bigint)), partial_sum(cast(CASE WHEN (isnotnull(customer_sk#8) AND isnotnull(customer_sk#14)) THEN 1 ELSE 0 END as bigint))]
Aggregate Attributes [3]: [sum#16, sum#17, sum#18]
Results [3]: [sum#19, sum#20, sum#21]

(28) Exchange
Input [3]: [sum#19, sum#20, sum#21]
Arguments: SinglePartition, true, [id=#22]

(29) HashAggregate [codegen id : 8]
Input [3]: [sum#19, sum#20, sum#21]
Keys: []
Functions [3]: [sum(cast(CASE WHEN (isnotnull(customer_sk#8) AND isnull(customer_sk#14)) THEN 1 ELSE 0 END as bigint)), sum(cast(CASE WHEN (isnull(customer_sk#8) AND isnotnull(customer_sk#14)) THEN 1 ELSE 0 END as bigint)), sum(cast(CASE WHEN (isnotnull(customer_sk#8) AND isnotnull(customer_sk#14)) THEN 1 ELSE 0 END as bigint))]
Aggregate Attributes [3]: [sum(cast(CASE WHEN (isnotnull(customer_sk#8) AND isnull(customer_sk#14)) THEN 1 ELSE 0 END as bigint))#23, sum(cast(CASE WHEN (isnull(customer_sk#8) AND isnotnull(customer_sk#14)) THEN 1 ELSE 0 END as bigint))#24, sum(cast(CASE WHEN (isnotnull(customer_sk#8) AND isnotnull(customer_sk#14)) THEN 1 ELSE 0 END as bigint))#25]
Results [3]: [sum(cast(CASE WHEN (isnotnull(customer_sk#8) AND isnull(customer_sk#14)) THEN 1 ELSE 0 END as bigint))#23 AS store_only#26, sum(cast(CASE WHEN (isnull(customer_sk#8) AND isnotnull(customer_sk#14)) THEN 1 ELSE 0 END as bigint))#24 AS catalog_only#27, sum(cast(CASE WHEN (isnotnull(customer_sk#8) AND isnotnull(customer_sk#14)) THEN 1 ELSE 0 END as bigint))#25 AS store_and_catalog#28]

