> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://zuora.ferndocs.com/docs/platform/extensibility/mediation/meter-components/sources-and-targets/snowflake-as-a-source/design-queries-for-snowflake-source-runs/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://zuora.ferndocs.com/_mcp/server. # Design queries for Snowflake source runs > Design your Snowflake source query so that each run returns only the records you want to process for that run. Design your Snowflake source query so that each run returns only the records you want to process for that run. ## Why query design matters Mediation executes the configured Snowflake query exactly as written. It does not automatically inject processing windows, timestamps, or checkpoint values into the query. If the same query runs again and returns the same rows, those rows are processed again. Example: ``` SELECT * FROM CUSTOMER_USAGE; ``` Every time this query runs, all rows in the table are exported and processed. If no downstream deduplication exists, repeated runs can produce duplicate processing. ## Option 1: Filter by time window Use a date or timestamp filter when you want each run to process a defined time range, such as the current day, previous day, previous week, previous month, or a custom billing period. Example: ``` SELECT * FROM CUSTOMER_USAGE WHERE DATE_TRUNC('month', created_at) = DATE_TRUNC('month', CURRENT_DATE()); ``` ## Option 2: Maintain processing metadata For recurring production workloads, many customers maintain a metadata table that stores the processing window for the next meter run. Your query can read that window and return only the next unprocessed range. Example: ``` WITH bounds AS ( SELECT start_datetime, end_datetime FROM meter_run WHERE latest = TRUE ) SELECT t.* FROM CUSTOMER_USAGE t CROSS JOIN bounds b WHERE t.created_at >= b.start_datetime AND t.created_at < b.end_datetime; ``` ## Option 3: External orchestration Customers can also orchestrate Snowflake processing externally. Examples include Zuora Workflow, enterprise schedulers, CI/CD pipelines, and other workflow automation tools. ## Filter at the source Filtering can be performed directly in Snowflake using Query mode. Filtering at the source is generally preferred because less data is exported, transferred, and processed downstream. You can still use a Filter operator in the pipeline for additional record-level filtering. Examples: ``` SELECT * FROM CUSTOMER_USAGE WHERE account_number = 'A1001' ``` ``` SELECT * FROM CUSTOMER_USAGE WHERE DATE(event_time) = CURRENT_DATE() ``` ## Incremental processing and duplicates The Snowflake source does not maintain processing offsets or automatically exclude previously processed rows. If duplicate processing must be avoided, design the query so that each run retrieves only the intended processing window, or implement downstream deduplication using a unique business key. ## Handle Snowflake column name case sensitivity When you configure a Snowflake source, ensure that the column names returned by your query match the field names defined in your event schema. By default, Snowflake converts unquoted identifiers to uppercase. As a result, a query such as `SELECT accountNumber FROM accounts;` returns the column name as `ACCOUNTNUMBER`, not `accountNumber`. If your event schema expects `accountNumber`, Mediation cannot map the returned data correctly. The meter can still process the expected number of records successfully, but the field values in the audit trail, and in downstream processing that depends on those fields, can appear blank because of the name mismatch. To preserve the required column names, use quoted aliases in your query. ``` SELECT accountNumber AS "accountNumber", chargeNumber AS "chargeNumber" FROM accounts; ``` Alternatively, define your event schema by using the exact column names returned by Snowflake. For more information about Snowflake identifier behavior, see [Snowflake identifier requirements](https://docs.snowflake.com/en/sql-reference/identifiers-syntax#unquoted-identifiers). Example Query ``` SELECT accountNumber, chargeNumber FROM usage_data; ``` Snowflake output ``` ACCOUNTNUMBER CHARGENUMBER ``` Event schema ``` accountNumber chargeNumber ``` Because the event schema expects `accountNumber` while the query returns `ACCOUNTNUMBER`, the mapping fails and the audit trail displays blank field values. Best Practices: * Use quoted aliases (`AS "fieldName"`) to preserve the desired column names. * Ensure the event schema field names exactly match the column names returned by the query, including case. * Verify the generated JSON output if you are unsure how Snowflake is returning column names. > Design your Snowflake source query so that each run returns only the records you want to process for that run. ## Docs - [Schedule and run Snowflake source meters](https://zuora.ferndocs.com/docs/platform/extensibility/mediation/meter-components/sources-and-targets/snowflake-as-a-source/design-queries-for-snowflake-source-runs/schedule-and-run-snowflake-source-meters.md): A Snowflake source runs only when a meter run is started.