### Example print_profile_docs output Source: https://github.com/data-mie/dbt-profiler/blob/main/README.md This is an example of the Markdown table output generated by the print_profile_docs macro, wrapped in a Jinja docs block. It displays profiling information for a relation. ```jinja {% docs dbt_profiler__customers %} | column_name | data_type | not_null_proportion | distinct_proportion | distinct_count | is_unique | min | max | | ----------------------- | --------- | ------------------- | ------------------- | -------------- | --------- | ---------- | ---------- | | customer_id | int64 | 1.00 | 1.00 | 100 | 1 | 1 | 100 | | first_order | date | 0.62 | 0.46 | 46 | 0 | 2018-01-01 | 2018-04-07 | | most_recent_order | date | 0.62 | 0.52 | 52 | 0 | 2018-01-09 | 2018-04-09 | | number_of_orders | int64 | 0.62 | 0.04 | 4 | 0 | 1 | 5 | | customer_lifetime_value | float64 | 0.62 | 0.35 | 35 | 0 | 1 | 99 | {% enddocs %} ``` -------------------------------- ### Get profile table with relation name Source: https://github.com/data-mie/dbt-profiler/blob/main/README.md This example shows how to use the `get_profile_table` macro by providing the `relation_name` argument. This macro returns an agate.Table object. ```sql {% set table = dbt_profiler.get_profile_table(relation_name="customers") %} ``` -------------------------------- ### Create Custom Adapter File Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/adapter-implementations.md Example of creating a custom adapter file for a new database, defining the measure_median macro. This macro handles numeric and non-struct data types. ```jinja2 {# dbt_packages/dbt_profiler/macros/adapters/my_db.sql #} {% macro my_db__measure_median(column_name, data_type, cte_name) %} {% if dbt_profiler.is_numeric_dtype(data_type) and not dbt_profiler.is_struct_dtype(data_type) %} {# Your custom median SQL #} my_db_percentile({{ adapter.quote(column_name) }}, 0.5) {% else %} cast(null as {{ dbt.type_numeric() }}) {% endif %} {% endmacro %} ``` -------------------------------- ### Install dbt-profiler Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/getting-started.md Add dbt-profiler to your dbt project's packages.yml file and run 'dbt deps' to install. ```yaml packages: - package: data-mie/dbt_profiler version: 0.9.0 # Use the latest version ``` ```bash dbt deps ``` -------------------------------- ### dbt Schema Structure Example Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile-schema.md This is an example of the dictionary structure representing the dbt schema that the macro returns. It includes version, model details, and column metadata. ```json { "version": 2, "models": [ { "name": "relation_name", "description": "model_description", "columns": [ { "name": "column_name", "description": "column_description", "meta": { "data_type": "...", "row_count": 100.0, "not_null_proportion": 0.95, ... } }, ... ] } ] } ``` -------------------------------- ### Example schema.yml output with profile data Source: https://github.com/data-mie/dbt-profiler/blob/main/README.md This YAML output demonstrates the structure of a schema.yml file generated by the print_profile_schema macro. It includes model and column descriptions, along with detailed profiling metrics within the 'meta' section for each column. ```yaml version: 2 models: - name: customers description: '' columns: - name: customer_id description: '' meta: data_type: int64 row_count: 100.0 not_null_proportion: 1.0 distinct_proportion: 1.0 distinct_count: 100.0 is_unique: 1.0 min: '1' max: '100' avg: 50.5 std_dev_population: 28.86607004772212 std_dev_sample: 29.01149197588202 profiled_at: '2022-01-13 10:08:18.446822+00' - name: first_order description: '' meta: data_type: date row_count: 100.0 not_null_proportion: 0.62 distinct_proportion: 0.46 distinct_count: 46.0 is_unique: 0.0 min: '2018-01-01' max: '2018-04-07' avg: null std_dev_population: null std_dev_sample: null profiled_at: '2022-01-13 10:08:18.446822+00' # ... remaining columns ``` -------------------------------- ### Get profile with a WHERE clause Source: https://github.com/data-mie/dbt-profiler/blob/main/README.md When using the `get_profile` macro, you can specify a `where_clause` to filter records before profiling. This example filters for active customers. ```sql {{ dbt_profiler.get_profile(relation=ref("customers"), where_clause="is_active = true") }} ``` -------------------------------- ### Scheduled Profile Refresh (Cron) Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/getting-started.md Set up a cron job for a daily profile refresh at 2 AM UTC. This example assumes a dbt project with a 'profile' tag and a specified profiles directory. ```bash # Example: Daily refresh at 2 AM UTC # Implemented as a GitHub Actions workflow or similar 0 2 * * * dbt run -s tag:profile --profiles-dir ~/.dbt ``` -------------------------------- ### Get Profile Table Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/INDEX.md Retrieves the profile results as a table, which can then be iterated over. ```APIDOC ## get_profile_table ### Description Retrieves the data profile results in a table format, suitable for iteration. ### Usage ```sql {% set profile = dbt_profiler.get_profile_table(relation, where_clause, exclude_measures, include_columns, exclude_columns, group_by) %} ``` ### Parameters (Same as `get_profile`) ### Example ```jinja2 {% set profile = dbt_profiler.get_profile_table(relation=ref("orders")) %} {% for row in profile.rows %} Column {{ row.get("column_name") }} has {{ row.get("distinct_count") }} distinct values {% endfor %} ``` ``` -------------------------------- ### Access Specific Columns from Profile Table Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-get-profile-table.md Retrieve a profile table and then access specific columns by name from the result. This example demonstrates logging all column names and accessing data type and null rate for the first row's column. ```jinja2 {% set profile = dbt_profiler.get_profile_table(relation=ref("users")) %} {% for column_name in profile.column_names %} {{ log("Column: " ~ column_name, info=True) }} {% endfor %} {% set first_column = profile.rows[0] %} Data type: {{ first_column.get("data_type") }} Null rate: {{ first_column.get("not_null_proportion") }} ``` -------------------------------- ### Inline Profile Model with dbt-profiler Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/00-START-HERE.md Use this pattern to generate a profile for a specific dbt model directly within your SQL code. Ensure the dbt-profiler package is installed and configured. ```sql {{ dbt_profiler.get_profile(relation=ref("customers")) }} ``` -------------------------------- ### Get Profile SQL Query Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/INDEX.md Generates a SQL query string for profiling a dbt relation. Use this when you need to embed profiling results directly into your dbt models. ```jinja2 {{ dbt_profiler.get_profile( relation=ref("my_table"), exclude_measures=[], include_columns=[], exclude_columns=[], where_clause=none, group_by=[] ) }} ``` -------------------------------- ### Run and Test Adapter Implementations Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/adapter-implementations.md Navigate to the integration tests directory and run dbt with your specific adapter target. This ensures your adapter is correctly integrated and passes all defined tests. ```bash cd integration_tests dbt run --target your_adapter dbt test --target your_adapter ``` -------------------------------- ### Get profile excluding specific measures Source: https://github.com/data-mie/dbt-profiler/blob/main/README.md The `get_profile` macro allows you to exclude certain measures from the profiling results using the `exclude_measures` argument. This example excludes standard deviation measures. ```sql {{ dbt_profiler.get_profile(relation=source("jaffle_shop","customers"), exclude_measures=["std_dev_population", "std_dev_sample"]) }} ``` -------------------------------- ### Generate and Serve dbt Docs Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile-docs.md These bash commands are used to generate the dbt documentation site and then serve it locally for viewing. ```bash dbt docs generate dbt docs serve ``` -------------------------------- ### Basic Docs Generation Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile-docs.md Generate a docs block for a model named 'customers'. This is the most basic usage of the macro. ```bash dbt run-operation print_profile_docs --args '{"relation_name": "customers"}' ``` -------------------------------- ### Generate Profile Docs with Script Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/getting-started.md Alternatively, use the provided shell script to generate profile documentation for a given relation. ```bash ./update-relation-profile.sh customers ``` -------------------------------- ### is_struct_dtype Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/utility-macros.md Checks if a data type is a complex/struct type. It matches types that start with 'struct' when lowercased. ```APIDOC ## is_struct_dtype ### Description Determines if a data type represents a complex/struct type. ### Signature ```jinja2 {% macro is_struct_dtype(dtype) %} ``` ### Parameters #### Parameters - **dtype** (string) - Lowercased data type from information schema ### Return Type Boolean ### Matches Types (lowercased) starting with `struct` ### Example ```jinja2 {% if not dbt_profiler.is_struct_dtype(data_type) %} {# Compute distinct measures for non-struct types #} count(distinct {{ column }}) {% endif %} ``` ``` -------------------------------- ### Basic Profile Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile.md Prints the profile of a specified dbt model to the console. Ensure the model name is correctly provided. ```bash dbt run-operation print_profile --args '{"relation_name": "customers"}' ``` -------------------------------- ### Override Custom Type String Macro Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/adapter-implementations.md Example of overriding the type_string utility macro in a custom adapter. ```jinja2 {% macro my_db__type_string() %} text {% endmacro %} ``` -------------------------------- ### Executing Profile Query with get_profile_table Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/architecture.md Demonstrates the usage of the get_profile_table macro, which executes the profile query immediately and returns results as an agate.Table. ```jinja2 {% set results = dbt_profiler.get_profile_table(...) %} {# Executes the query immediately, returns agate.Table #} ``` -------------------------------- ### Configure dbt Project for Docs Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/getting-started.md Add a 'docs-paths' configuration to your 'dbt_project.yml' file to specify where profile documentation will be stored. ```yaml model-paths: ["models"] docs-paths: ["docs"] ``` -------------------------------- ### Get Profile Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/INDEX.md Retrieves a data profile for a given dbt relation. This is the primary function for profiling data. ```APIDOC ## get_profile ### Description Generates a data profile for a specified dbt relation. ### Usage ```sql {{ dbt_profiler.get_profile(relation, where_clause, exclude_measures, include_columns, exclude_columns, group_by) }} ``` ### Parameters #### relation (Relation, optional) - dbt relation object (from `ref()` or `source()`) - Either this or `relation_name` must be provided #### relation_name (string, optional) - Name of the table/view to profile - Either this or `relation` must be provided #### schema (string, optional) - Schema containing the relation - Default: `target.schema` - Only needed with `relation_name` #### database (string, optional) - Database containing the relation - Default: `target.database` - Only needed with `relation_name` #### exclude_measures (List[string], optional) - Measures to exclude from profile - Default: `[]` (all measures included) - Valid values: `row_count`, `not_null_proportion`, `distinct_proportion`, `distinct_count`, `is_unique`, `min`, `max`, `avg`, `median`, `std_dev_population`, `std_dev_sample` #### include_columns (List[string], optional) - Columns to include in profile - Default: `[]` (all columns) - Cannot be used with `exclude_columns` #### exclude_columns (List[string], optional) - Columns to exclude from profile - Default: `[]` - Cannot be used with `include_columns` #### where_clause (string, optional) - SQL WHERE clause to filter rows before profiling - Default: `none` (all rows) - Applied in a source CTE #### group_by (List[string], optional) - Column names to group profile by - Default: `[]` (one profile per column) - Produces one row per group per column - Profile result includes group columns ### Example ```jinja2 {{ dbt_profiler.get_profile( relation=ref("customers"), where_clause="event_date >= current_date - 30", exclude_measures=["std_dev_population", "std_dev_sample", "median"], include_columns=["user_id", "email", "created_at"] ) }} ``` ``` -------------------------------- ### is_date_or_time_dtype Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/utility-macros.md Determines if a given data type string represents a date or time-related type. It checks if the type starts with 'timestamp' or 'date'. ```APIDOC ## is_date_or_time_dtype ### Description Determines if a data type represents a date or time type. ### Signature ```jinja2 {% macro is_date_or_time_dtype(dtype) %} ``` ### Parameters #### Parameters - **dtype** (string) - Lowercased data type from information schema ### Return Type Boolean ### Matches Types starting with: `timestamp`, `date` ### Example ```jinja2 {% if dbt_profiler.is_date_or_time_dtype(data_type) %} {# Compute min/max for temporal columns #} {% endif %} ``` ``` -------------------------------- ### Profile a Model in SQL Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/getting-started.md Create a dbt model that uses the `get_profile` macro to profile a specified relation. Run the model using 'dbt run'. ```sql -- models/customers_profile.sql {{ dbt_profiler.get_profile(relation=ref("customers")) }} ``` ```bash dbt run -s customers_profile ``` -------------------------------- ### Adapter Dispatch Pattern for get_profile Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/architecture.md Demonstrates how the adapter dispatch pattern is used to support database-specific implementations of the get_profile macro. This allows for a single macro interface that works across different databases. ```jinja2 {% macro get_profile(...) %} {{ return(adapter.dispatch("get_profile", macro_namespace="dbt_profiler")(args)) }} {% endmacro %} {% macro default__get_profile(...) %} {# Default SQL-92 compatible implementation #} {% endmacro %} {% macro bigquery__get_profile(...) %} {# BigQuery-specific optimizations #} {% endmacro %} ``` -------------------------------- ### Override Measure for Specific Database Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/architecture.md Create adapter-specific macros to customize measure behavior for a particular database. This example overrides the `measure_median` macro. ```jinja2 {# dbt/macros/adapters/my_db.sql #} {% macro my_db__measure_median(column_name, data_type, cte_name) %} {% if dbt_profiler.is_numeric_dtype(data_type) %} my_custom_percentile_func({{ adapter.quote(column_name) }}, 0.5) {% else %} cast(null as {{ dbt.type_numeric() }}) {% endif %} {% endmacro %} ``` -------------------------------- ### Override Custom Distinct Count Macro Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/adapter-implementations.md Example of overriding the measure_distinct_count macro in a custom adapter. This implementation handles non-struct data types. ```jinja2 {% macro my_db__measure_distinct_count(column_name, data_type) %} {% if not dbt_profiler.is_struct_dtype(data_type) %} {# Custom distinct count logic #} count(distinct {{ adapter.quote(column_name) }}) {% else %} cast(null as {{ dbt.type_numeric() }}) {% endif %} {% endmacro %} ``` -------------------------------- ### Override Custom Information Schema Macro Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/adapter-implementations.md Example of overriding the information_schema utility macro in a custom adapter, specifying a custom schema for catalog information. ```jinja2 {% macro my_db__information_schema(relation) %} {# Custom information schema logic #} {{ relation.database }}.pg_catalog.pg_attribute {% endmacro %} ``` -------------------------------- ### Implement Adapter Dispatch Pattern for Utility Macros Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/utility-macros.md This pattern allows for database-specific overrides of utility macros. Create a default implementation and then specific ones for adapters like BigQuery. ```jinja {% macro utility_name(...) %} {{ return(adapter.dispatch("utility_name", macro_namespace="dbt_profiler")(...)) }} {% endmacro %} {% macro default__utility_name(...) %} {# Default implementation #} {% endmacro %} {% macro bigquery__utility_name(...) %} {# BigQuery-specific implementation #} {% endmacro %} ``` ```jinja {% macro {{your_adapter}}__utility_name(...) %} {# Your custom implementation #} {% endmacro %} ``` -------------------------------- ### Generate Profile Docs via dbt CLI Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile-docs.md This bash command demonstrates how to run the print_profile_docs macro and redirect its output to a markdown file. Ensure the relation_name argument matches your target relation. ```bash dbt run-operation print_profile_docs \ --args '{"relation_name": "customers"}' > docs/dbt_profiler__customers.md ``` -------------------------------- ### Get Profile as Agate Table Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/INDEX.md Returns an agate.Table object containing profiling results. This is useful for further data manipulation or analysis within dbt macros. ```jinja2 {% set profile = dbt_profiler.get_profile_table( relation=ref("my_table"), exclude_measures=[], include_columns=[], exclude_columns=[], where_clause=none ) %} ``` -------------------------------- ### Check if Data Type is Struct Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/utility-macros.md This macro checks if a data type string represents a complex/struct type. It matches types starting with 'struct' (case-insensitive). ```jinja2 {% macro is_struct_dtype(dtype) %} ``` ```jinja2 {% if not dbt_profiler.is_struct_dtype(data_type) %} {# Compute distinct measures for non-struct types #} count(distinct {{ column }}) {% endif %} ``` -------------------------------- ### Configure dbt Project for Docs Folder Source: https://github.com/data-mie/dbt-profiler/blob/main/README.md Add a 'docs' folder to your `dbt_project.yml` to manage documentation files. ```yaml model-paths: ["models", "docs"] ``` -------------------------------- ### Get Information Schema Location Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/utility-macros.md Retrieves the information schema location specific to the database implementation. For BigQuery, it returns 'database.schema.INFORMATION_SCHEMA'; for others, it uses the default relation.information_schema(). ```jinja2 {% macro information_schema(relation) %} ``` ```jinja2 {% set info_schema = dbt_profiler.information_schema(my_relation) %} select * from {{ info_schema }}.COLUMNS ``` -------------------------------- ### Generate Profile Documentation for a Model Source: https://github.com/data-mie/dbt-profiler/blob/main/README.md Run the `print_profile_docs` operation to generate a Markdown file containing profile results for a specific model. Store the output in a variable before redirecting to a file to avoid compilation errors. ```bash # docs/dbt_profiler/customers.md dbt run-operation print_profile_docs --args '{"relation_name": "customers"}' ``` -------------------------------- ### Inline Profile in a dbt Model Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/getting-started.md Embed a data profile directly within a dbt model definition. This snippet shows how to get the profile for the 'orders' relation. ```sql -- models/staging/stg_orders_profile.sql select * from {{ dbt_profiler.get_profile(relation=ref("orders")) }} ``` -------------------------------- ### Run dbt Seed, Run, and Test Commands Source: https://github.com/data-mie/dbt-profiler/blob/main/integration_tests/README.md Execute these commands to seed data, run dbt models, and perform tests against your configured PostgreSQL profile. ```bash dbt seed -t postgres dbt run -t postgres dbt test -t postgres ``` -------------------------------- ### Conditional dbt Profiling Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/INDEX.md Execute the `get_profile` macro conditionally based on the dbt execution context. This allows for dynamic profiling, for example, only running on certain environments or conditions. ```jinja {% if execute %} {{ dbt_profiler.get_profile(relation=ref("large_table")) }} {% endif %} ``` -------------------------------- ### print_profile_docs Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/INDEX.md Creates a Jinja documentation block that includes a profile table. This is useful for embedding profile summaries directly into dbt documentation. It is invoked using `dbt run-operation` with the relation name. ```APIDOC ## print_profile_docs ### Description Generates a Jinja docs block containing a profile table. ### Method dbt run-operation ### Arguments - **relation_name**: The name of the dbt relation to profile. ``` -------------------------------- ### Get dbt Relation Object Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/utility-macros.md Resolves a relation name, schema, and database into a dbt relation object. Use when you need to programmatically reference a database table or view. ```jinja2 { {% macro get_relation(relation=none, relation_name=none, schema=none, database=none) %} } ``` ```jinja2 {% set my_relation = dbt_profiler.get_relation(relation_name="customers", schema="analytics") %} ``` -------------------------------- ### SQL Generation for get_profile Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/architecture.md Shows how the primary get_profile macro generates a SQL query string instead of executing it directly. This allows profiles to be embedded in dbt models. ```jinja2 {% set profile_sql = dbt_profiler.get_profile(relation=ref("customers")) %} {# Returns a SELECT statement as a string, not the result set #} ``` -------------------------------- ### print_profile Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/INDEX.md Executes a dbt run-operation command to print a formatted ASCII table of the profile data directly to the console. Requires the relation name as an argument. ```APIDOC ## print_profile ### Description Prints a formatted ASCII table to console. ### Method dbt run-operation ### Arguments - **relation_name**: The name of the dbt relation to profile. ``` -------------------------------- ### Check if Data Type is Date or Time Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/utility-macros.md Use this macro to determine if a given data type string represents a date or time. It matches types starting with 'timestamp' or 'date'. ```jinja2 {% macro is_date_or_time_dtype(dtype) %} ``` ```jinja2 {% if dbt_profiler.is_date_or_time_dtype(data_type) %} {# Compute min/max for temporal columns #} {% endif %} ``` -------------------------------- ### Generate Schema with Descriptions Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile-schema.md Include model and column descriptions in the generated schema.yml. Provide descriptions as arguments. ```bash dbt run-operation print_profile_schema --args '{ "relation_name": "orders", "model_description": "Core orders data with customer and product information", "column_description": "See dbt_profiler for data quality metrics" }' ``` -------------------------------- ### Get Database-Specific String Type Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/utility-macros.md Returns the appropriate string or varchar type name for the current database. Use this macro to ensure SQL compatibility when casting columns to string types. ```jinja2 {% macro type_string() %} ``` ```jinja2 {% set str_type = dbt_profiler.type_string() %} cast(my_column as {{ str_type }}) ``` -------------------------------- ### Print Profile Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/INDEX.md Prints the data profile to the dbt console. ```APIDOC ## print_profile ### Description Prints the data profile to the dbt console with configurable display limits. ### Usage ```sql {{ dbt_profiler.print_profile(relation, max_rows, max_columns, max_column_width, max_precision) }} ``` ### Parameters #### relation (Relation, optional) - dbt relation object (from `ref()` or `source()`) - Either this or `relation_name` must be provided #### relation_name (string, optional) - Name of the table/view to profile - Either this or `relation` must be provided #### schema (string, optional) - Schema containing the relation - Default: `target.schema` - Only needed with `relation_name` #### database (string, optional) - Database containing the relation - Default: `target.database` - Only needed with `relation_name` #### max_rows (int, optional) - Maximum rows to display - Default: `none` (no limit) #### max_columns (int, optional) - Maximum columns to display - Default: `13` #### max_column_width (int, optional) - Maximum width per column in characters - Default: `30` #### max_precision (int, optional) - Maximum decimal precision for numbers - Default: `none` (no limit) ### Example ```jinja2 {{ dbt_profiler.print_profile( relation=ref("customers"), max_rows=100, max_columns=10 ) }} ``` ``` -------------------------------- ### Configure dbt Project for Docs Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile-docs.md This YAML snippet shows how to configure your dbt_project.yml file to include a 'docs' directory for custom documentation files. ```yaml # dbt_project.yml model-paths: ["models"] docs-paths: ["docs"] ``` -------------------------------- ### Alternative for dbt Cloud: Log profile rows Source: https://github.com/data-mie/dbt-profiler/blob/main/README.md This SQL snippet provides an alternative for dbt Cloud users, as the standard print_profile macro does not work in that environment. It retrieves the profile and logs each row's values to the console without Markdown formatting. ```sql {% set profile = dbt_profiler.get_profile(relation=ref("customers")) %} {% for row in profile.rows %} {% do log(row.values(), info=True) %} {% endfor %} ``` -------------------------------- ### Profile a Sample of Data Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/00-START-HERE.md To improve performance on very large tables, profile a random sample of the data instead of the entire dataset. Adjust the `where_clause` to control the sample size. ```jinja2 where_clause="random() < 0.01" -- 1% sample ``` -------------------------------- ### Print Profile to Console Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/INDEX.md Runs a dbt operation to print a formatted ASCII table of the profile to the console. Useful for quick inspection of profiling results. ```bash dbt run-operation print_profile --args '{"relation_name": "my_table"}' ``` -------------------------------- ### Print Profile Schema Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/INDEX.md Prints the data profile schema, allowing for custom descriptions. ```APIDOC ## print_profile_schema ### Description Prints the data profile schema, enabling the addition of custom model and column descriptions. ### Usage ```sql {{ dbt_profiler.print_profile_schema(relation, model_description, column_description, max_columns, max_column_width, max_precision) }} ``` ### Parameters #### relation (Relation, optional) - dbt relation object (from `ref()` or `source()`) - Either this or `relation_name` must be provided #### relation_name (string, optional) - Name of the table/view to profile - Either this or `relation` must be provided #### schema (string, optional) - Schema containing the relation - Default: `target.schema` - Only needed with `relation_name` #### database (string, optional) - Database containing the relation - Default: `target.database` - Only needed with `relation_name` #### model_description (string, optional) - Description for the model in generated schema - Default: `""` #### column_description (string, optional) - Description for all columns (same for all) - Default: `""` #### max_columns (int, optional) - Maximum columns to display - Default: `13` #### max_column_width (int, optional) - Maximum width per column in characters - Default: `30` #### max_precision (int, optional) - Maximum decimal precision for numbers - Default: `none` (no limit) ### Example ```jinja2 {{ dbt_profiler.print_profile_schema( relation=ref("users"), model_description="This table contains user information.", column_description="All columns are text types." ) }} ``` ``` -------------------------------- ### Reference Profile Docs in Schema Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/getting-started.md Embed the generated profile documentation within your model's description in 'schema.yml' using the 'doc()' macro. This makes the profile accessible when viewing dbt docs. ```yaml version: 2 models: - name: customers description: | Customer master data. **Data Quality Profile:** {{ doc("dbt_profiler__customers") }} columns: - name: customer_id description: Unique customer identifier tests: - unique - not_null ``` -------------------------------- ### dbt-profiler Project Structure Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/architecture.md This tree outlines the directory structure of the dbt-profiler package, detailing the location of macros, integration tests, and configuration files. ```tree dbt-profiler/ ├── macros/ │ ├── get_profile.sql │ ├── get_profile_table.sql │ ├── print_profile.sql │ ├── print_profile_schema.sql │ ├── print_profile_docs.sql │ ├── measures.sql │ ├── cross_db_utils.sql │ ├── relation.sql │ └── adapters/ │ ├── postgres.sql │ ├── bigquery.sql │ ├── snowflake.sql │ ├── databricks.sql │ ├── oracle.sql │ ├── redshift.sql │ ├── sqlserver.sql │ └── athena.sql ├── integration_tests/ │ ├── models/ │ │ ├── profile.sql │ │ ├── profile_exclude_measures.sql │ │ ├── profile_exclude_columns.sql │ │ ├── profile_include_columns.sql │ │ ├── profile_group_by.sql │ │ ├── profile_struct.sql │ │ └── ... │ └── dbt_project.yml ├── dbt_project.yml ├── README.md └── LICENSE ``` -------------------------------- ### Generate Basic Schema Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile-schema.md Use this to generate a basic schema.yml for a model. Specify the relation_name to target. ```bash dbt run-operation print_profile_schema --args '{"relation_name": "customers"}' ``` -------------------------------- ### Profile with Aggregation using dbt-profiler Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/00-START-HERE.md This pattern allows you to profile a dbt model while aggregating results by specified columns. Useful for understanding data characteristics across different dimensions. Requires the dbt-profiler package. ```jinja2 {{ dbt_profiler.get_profile( relation=ref("sales"), group_by=["region", "year"] ) }} ``` -------------------------------- ### print_profile_docs Macro Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile-docs.md Generates a Markdown table of profile metrics wrapped in a dbt Jinja `docs` block. This macro is useful for integrating profiling data into dbt documentation without directly modifying `schema.yml` files. ```APIDOC ## Macro: print_profile_docs ### Description Generates a Markdown table of profile metrics within a dbt Jinja `docs` block. This is designed to be used with the dbt docs workflow, allowing profile data to be stored separately from `schema.yml` files while remaining available in dbt documentation. ### Signature ```jinja2 {% macro print_profile_docs(relation=none, relation_name=none, docs_name=none, schema=none, database=none, exclude_measures=[], include_columns=[], exclude_columns=[], max_rows=none, max_columns=13, max_column_width=30, max_precision=none, where_clause=none) %} ``` ### Parameters #### Macro Parameters - **relation** (Relation) - Optional - Either `relation` or `relation_name` must be provided. dbt relation object to profile. - **relation_name** (string) - Optional - Either `relation` or `relation_name` must be provided. Name of the relation to profile. - **docs_name** (string) - Optional - Default: `dbt_profiler__{{relation_name}}`. Name of the generated `docs` block. - **schema** (string) - Optional - Default: `target.schema`. Schema where the relation exists. - **database** (string) - Optional - Default: `target.database`. Database where the relation exists. - **exclude_measures** (List[string]) - Optional - Default: `[]`. List of measures to exclude. - **include_columns** (List[string]) - Optional - Default: `[]`. Columns to include in profile. - **exclude_columns** (List[string]) - Optional - Default: `[]`. Columns to exclude from profile. - **max_rows** (int) - Optional - Default: `none`. Maximum number of rows to display. - **max_columns** (int) - Optional - Default: `13`. Maximum number of columns to display. - **max_column_width** (int) - Optional - Default: `30`. Maximum width in characters for each column. - **max_precision** (int) - Optional - Default: `none`. Maximum decimal precision for numeric types. - **where_clause** (string) - Optional - Default: `none`. SQL WHERE clause to filter records before profiling. ``` -------------------------------- ### Print Profile Docs Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/INDEX.md Prints the data profile in a format suitable for dbt documentation. ```APIDOC ## print_profile_docs ### Description Prints the data profile in a format suitable for dbt documentation, with options for naming the docs block. ### Usage ```sql {{ dbt_profiler.print_profile_docs(relation, docs_name, max_columns, max_column_width, max_precision) }} ``` ### Parameters #### relation (Relation, optional) - dbt relation object (from `ref()` or `source()`) - Either this or `relation_name` must be provided #### relation_name (string, optional) - Name of the table/view to profile - Either this or `relation` must be provided #### schema (string, optional) - Schema containing the relation - Default: `target.schema` - Only needed with `relation_name` #### database (string, optional) - Database containing the relation - Default: `target.database` - Only needed with `relation_name` #### docs_name (string, optional) - Name of the generated docs block - Default: `dbt_profiler__{{relation_name}}` #### max_columns (int, optional) - Maximum columns to display - Default: `13` #### max_column_width (int, optional) - Maximum width per column in characters - Default: `30` #### max_precision (int, optional) - Maximum decimal precision for numbers - Default: `none` (no limit) ### Example ```jinja2 {{ dbt_profiler.print_profile_docs( relation=ref("huge_table"), docs_name="my_huge_table_profile" ) }} ``` ``` -------------------------------- ### Iterate Profile Results in a dbt Macro Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/00-START-HERE.md This pattern demonstrates how to retrieve profile results as a table within a dbt macro and iterate over each row to access column-specific profiling information. Requires dbt-profiler. ```jinja2 {% set profile = dbt_profiler.get_profile_table(relation=ref("orders")) %} {% for row in profile.rows %} {{ row.get("column_name") }}: {{ row.get("not_null_proportion") }} {% endfor %} ``` -------------------------------- ### Generate Profile Docs for a Relation Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/getting-started.md Use the 'print_profile_docs' dbt run-operation to generate a markdown file containing the data quality profile for a specified relation. The output is redirected to a markdown file within the configured docs directory. ```bash dbt run-operation print_profile_docs \ --args '{"relation_name": "customers"}' \ > docs/dbt_profiler__customers.md ``` -------------------------------- ### Profile with Limited Display Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile.md Profiles a dbt model and limits the display size by setting the maximum number of columns, maximum column width, and maximum precision for numeric values. ```bash dbt run-operation print_profile --args '{ "relation_name": "users", "max_columns": 7, "max_column_width": 20, "max_precision": 2 }' ``` -------------------------------- ### Custom Docs Name Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile-docs.md Generate a docs block with a custom name 'event_quality_profile' for the 'events' model. Useful for organizing documentation. ```bash dbt run-operation print_profile_docs --args '{ "relation_name": "events", "docs_name": "event_quality_profile" }' ``` -------------------------------- ### Generate Profile Docs Block Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/INDEX.md Generates a Jinja docs block that includes a profile table. This is helpful for embedding profiling summaries directly into your dbt documentation. ```bash dbt run-operation print_profile_docs --args '{"relation_name": "my_table"}' ``` -------------------------------- ### Limit Display Size Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile-docs.md Control the output size for readability when generating a docs block for the 'users' model. Options include limiting the number of columns, column width, and precision. ```bash dbt run-operation print_profile_docs --args '{ "relation_name": "users", "max_columns": 8, "max_column_width": 25, "max_precision": 3 }' ``` -------------------------------- ### Conditional execution of get_profile Source: https://github.com/data-mie/dbt-profiler/blob/main/README.md This snippet demonstrates how to conditionally execute the `get_profile` macro using Jinja's `execute` mode, often used for tasks that should only run during dbt's execution phase. ```sql -- depends_on: {{ ref("customers") }} {% if execute %} {{ dbt_profiler.get_profile(relation=ref("customers")) }} {% endif %} ``` -------------------------------- ### Lazy Information Schema Lookup Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/architecture.md Illustrates how column data types are dynamically retrieved from the database information schema during profile generation. This ensures accurate type detection. ```jinja2 {% set information_schema_columns = run_query(dbt_profiler.select_from_information_schema_columns(relation)) %} ``` -------------------------------- ### print_profile Macro Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-print-profile.md The `print_profile` macro allows users to print a relation's profile as a Markdown table to standard output. It's useful for development and local testing. Note: This macro is not compatible with dbt Cloud. ```APIDOC ## print_profile Macro ### Description Prints a dbt relation's profile as a Markdown table to stdout. Useful for quick inspection during development or in local environments. Not compatible with dbt Cloud. ### Signature ```jinja2 {% macro print_profile(relation=none, relation_name=none, schema=none, database=none, exclude_measures=[], include_columns=[], exclude_columns=[], max_rows=none, max_columns=13, max_column_width=30, max_precision=none, where_clause=none) %} ``` ### Parameters #### Macro Parameters - **relation** (Relation) - Required - Either `relation` or `relation_name` must be provided. The dbt relation object to profile. - **relation_name** (string) - Required - Either `relation` or `relation_name` must be provided. The name of the relation to profile. - **schema** (string) - Optional - The schema where the relation exists. Defaults to `target.schema`. - **database** (string) - Optional - The database where the relation exists. Defaults to `target.database`. - **exclude_measures** (List[string]) - Optional - A list of measure names to exclude from the profile. Defaults to `[]`. - **include_columns** (List[string]) - Optional - A list of columns to include in the profile. Defaults to `[]`. - **exclude_columns** (List[string]) - Optional - A list of columns to exclude from the profile. Defaults to `[]`. - **max_rows** (int) - Optional - The maximum number of rows to display. `none` means no limit. Defaults to `none`. - **max_columns** (int) - Optional - The maximum number of columns to display before truncation. Defaults to `13`. - **max_column_width** (int) - Optional - The maximum width in characters for each column. Longer values are truncated. Defaults to `30`. - **max_precision** (int) - Optional - The maximum decimal precision for numeric types. `none` means no limit. Defaults to `none`. - **where_clause** (string) - Optional - A SQL WHERE clause to filter records before profiling. Defaults to `none`. ``` -------------------------------- ### Integrate dbt-profiler Documentation with dbt Docs Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/00-START-HERE.md Embed dbt-profiler documentation generated by the `doc()` function directly into your dbt model configurations. This allows for rich, dynamic documentation within your dbt project. Requires dbt-profiler and dbt Docs. ```yaml version: 2 models: - name: customers description: | Customer data. Profile: {{ doc("dbt_profiler__customers") }} ``` -------------------------------- ### SQL Implementation for std_dev_sample Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/measure-implementations.md Use `stddev_samp(column)` for numeric columns to calculate sample standard deviation. For non-numeric columns, cast to null. ```sql stddev_samp(column) ``` ```sql cast(null as numeric) ``` -------------------------------- ### Profile by Relation Name Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-get-profile-table.md Profile a table by its name, schema, and database when a dbt relation object is not directly available. Logs the number of columns profiled. ```jinja2 {% set profile = dbt_profiler.get_profile_table( relation_name="my_table", schema="analytics", database="my_database" ) %} {% set total_rows = profile.rows | length %} {{ log("Profiled " ~ total_rows ~ " columns", info=True) }} ``` -------------------------------- ### Profile All Columns in a dbt Model Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/macros-get-profile.md Use this snippet to profile all columns within a specified dbt model. Ensure the model reference is correct. ```sql -- models/customers_profile.sql {{ dbt_profiler.get_profile(relation=ref("customers")) }} ``` -------------------------------- ### PostgreSQL Median Implementation Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/adapter-implementations.md This snippet shows the PostgreSQL-specific implementation for calculating the median using the `percentile_cont()` ordered aggregate function. It is suitable for accurate median calculations, especially on smaller datasets. ```sql percentile_cont(0.5) within group (order by column) ``` -------------------------------- ### SQL Median Implementation (Default) Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/measure-implementations.md Provides a default approximate median calculation for numeric columns when a database-specific implementation is not available. ```sql median(column) ``` -------------------------------- ### Generate SELECT Query for Information Schema Columns Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/utility-macros.md Use this macro to generate a SQL query for retrieving column metadata from the information schema. It requires a dbt relation object as input. ```sql select * from {{ information_schema }}.COLUMNS where lower(table_schema) = lower('{{ schema }}') and lower(table_name) = lower('{{ identifier }}') order by ordinal_position asc ``` ```jinja {% set columns_query = dbt_profiler.select_from_information_schema_columns(my_relation) %} {% set columns = run_query(columns_query) %} ``` -------------------------------- ### Databricks Adapter: Measure Median Override Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/adapter-implementations.md Uses Databricks' 'percentile_approx' function for calculating the median, offering an efficient approximation suitable for large datasets. ```sql percentile_approx(column, 0.5) ``` -------------------------------- ### SQL Average Implementation Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/measure-implementations.md Use `avg(column)` for numeric columns. For boolean columns, use a case statement to convert TRUE/FALSE to 1/0 before averaging. Non-numeric columns will result in NULL. ```sql avg(column) ``` ```sql avg(case when column then 1 else 0 end) ``` ```sql cast(null as numeric) ``` -------------------------------- ### Conditional Profiling in Production Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/getting-started.md Execute profiling only in a production environment to avoid unnecessary computation in development or staging. Returns an empty result set in non-production environments. ```jinja2 {% if target.name == 'prod' %} select * from {{ dbt_profiler.get_profile(relation=ref("customers")) }} {% else %} select 1 as dummy where false -- Empty result in dev {% endif %} ``` -------------------------------- ### Measure Macro Interface Source: https://github.com/data-mie/dbt-profiler/blob/main/_autodocs/profile-measures.md Exposes a measure as a macro following a standard pattern. Includes a default implementation for SQL computation. ```jinja2 {% macro measure_row_count(column_name, data_type) %} {{ return(adapter.dispatch("measure_row_count", macro_namespace="dbt_profiler")(column_name, data_type)) }} {% endmacro %} {% macro default__measure_row_count(column_name, data_type) %} {# SQL computation #} {% endmacro %} ```