{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"type":"markdown"},"seo":{"title":"SQL on FHIR","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"sql-on-fhir","__idx":0},"children":["SQL on FHIR"]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Deprecated"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["SQL on FHIR is not currently available to new customers. This documentation is maintained for existing legacy users only. If you have questions about your current implementation, please contact your account team."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can query your FHIR data on the 1up Platform with the power of SQL and the business intelligence (BI) tools that you're most familiar with. Though the 1upHealth FHIR API makes it easy for you to operate on individual or bulk FHIR resources, it doesn't include built-in analytics. You can use SQL on FHIR to run your analytics, discover insights, and get value from your FHIR data."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["SQL on FHIR allows you to view your FHIR data in relational format, and access it over standard SQL connections. Before you use SQL on FHIR, we recommend that you review some basic concepts that will help understand how the product works, such as resources, resource types, and data mapping."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"fhir-resources","__idx":1},"children":["FHIR Resources"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The FHIR specification ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"http://hl7.org/fhir/R4/resourcelist.html"},"children":["defines over a hundred"]}," (and counting) types of data that form the basis of interoperability for different healthcare use cases. Commonly used FHIR resources include Patient, Encounter, ExplanationOfBenefit and Provider."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Every type of resource in SQL on FHIR is represented by a table. A row in one of those tables represents a single resource of that type."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"fhir-resource-identifiers","__idx":2},"children":["FHIR Resource Identifiers"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["FHIR resources can refer to each other, such as when an Encounter resource refers to a particular Patient resource. In the 1upHealth FHIR server, these references use local resource identifiers, in the form of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RESOURCE_TYPE/ID"]},". For example, if an Encounter references a Patient, the reference is in this format: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Patient/abc123"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"how-fhir-maps-to-relational-data","__idx":3},"children":["How FHIR Maps to Relational Data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Every FHIR resource is stored as its own table in SQL on FHIR. These tables follow the fhir_r4 schema are of the format ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fhir_r4.resourcetype"]},". For example, Patient resources can be found in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fhir_r4.patient"]}," table and Encounter resources are in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fhir_r4.encounter"]}," table."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The columns in each table directly relate to the FHIR specification for each resource. For example, the FHIR attribute ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["meta"]}," is represented by the SQL on FHIR column ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["meta"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Commonly referenced data that is of a simple data type have been unnested into their own columns. To use complex data types, such as arrays and structs, you must unnest them in your SQL queries."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"sql","__idx":4},"children":["SQL"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Structured Query Language (SQL) is used to query relational database systems. It is built into most common BI tools including Tableau, Looker, and Power BI. SQL on FHIR only provides read-only access to data. You cannot modify data using SQL."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["SQL on FHIR’s query engine is built on Amazon Redshift, and has a documented list of data types and supported features. SQL queries from other databases might not work without modification."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For information about the supported SQL dialect, see the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://docs.aws.amazon.com/redshift/latest/dg/cm_chap_SQLCommandRef.html"},"children":["Amazon Redshift SQL Reference"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"security-authentication-authorization--limits","__idx":5},"children":["Security, Authentication, Authorization & Limits"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The 1upHealth SQL on FHIR platform is HIPAA-compliant. Each environment is secured with multi-layer security, and an authentication and authorization architecture that is based on industry best practices. The strategies we use to protect your data are below:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Strategy"},"children":["Strategy"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Network security"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Access to your SQL endpoint is restricted to users on your VPN using source IP policies."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Data protection"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Data is secured by server-side encryption at rest and in-flight."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Authentication"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Authentication requires individual user accounts with access keys and secrets, which are securely distributed."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Authorization"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Individuals are assigned to groups with the correct roles for their SQL access."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Query limits & logging"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Data scanning limit per query is 500 GB and the data usage alert is set to 500 GB per hour."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"setup-your-sql-client","__idx":6},"children":["Setup your SQL client"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use any SQL client that supports Amazon Redshift as a data source. The following information may be needed to connect your BI tool to Amazon Redshift:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["JDBC Endpoint URL: Provided by 1upHealth.",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Example: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["jdbc:redshift://endpoint:port/database"]}]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Username: Your personal access key, provided by 1up."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Password: Your personal secret key, provided by 1up."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Reference the documentation for your tool on configuration instructions. A few popular tools are linked below:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://dbeaver.com/docs/dbeaver/Database-driver-Amazon-Redshift/"},"children":["DBeaver"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://help.tableau.com/current/pro/desktop/en-us/examples_amazonredshift.htm"},"children":["Tableau"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://learn.microsoft.com/en-us/power-bi/connect-data/desktop-data-sources"},"children":["Power BI"]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"data-types","__idx":7},"children":["Data types"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["SQL on FHIR defines what type of data can be stored in each column. This impacts the functions available for each column and is valuable to understand data returned from a query."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"simple-data-types","__idx":8},"children":["Simple data types"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following data types are used to describe singular values in a column. They can be further aggregated using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["super"]}," for more complex data types."]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["varchar"]}," — Variable length character string"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["bigint"]}," — 64-bit signed integer"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["double"]}," — 64-bit signed double-precision floating point number"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["boolean"]}," — Values are true and false"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["timestampz"]}," — Date and time, UTC timezone"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["date"]}," — Date is in ISO format (YYYY-MM-DD)"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"complex-data-types","__idx":9},"children":["Complex data types"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Complex data types contain collections of simple data types or nested data. Because of the nested nature of FHIR, several columns are represented by the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["super"]}," data type. You must use different notation to access the individual values inside this complex data type. See the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://docs.aws.amazon.com/redshift/latest/dg/c_Supported_data_types.html"},"children":["Amazon Redshift documentation"]}," for more detailed type information."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A few guidelines are listed below:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["super"]}," data type to store semi-structured data or documents as values."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["A super data type can either be an Amazon Redshift scalar value (such as a null, a boolean, a number, or string value) or a complex value (such as an array of values or a structure)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["To ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://docs.aws.amazon.com/redshift/latest/dg/query-super.html#unnest"},"children":["unnest this data type"]},", Amazon Redshift uses the PartiQL syntax to iterate over SUPER arrays in the FROM clause of a query."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"time-and-time-zones","__idx":10},"children":["Time and time zones"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["SQL on FHIR does not currently support time zone information, but timestamps are stored and processed as UTC. Where there is a timestamp given, such as in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["meta.lastUpdated"]}," field of any resource, you can assume it refers to UTC. This applies to the simple data types of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["timestampz"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["date"]},", either in their own columns or as part of a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["super"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"table-and-view-definitions","__idx":11},"children":["Table and view definitions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["SQL on FHIR includes enrichment tables, FHIR data tables, views that you can use to generate analytics and insights, and visibility into your FHIR data. You can use these definitions to write SQL queries and to help you understand the context of the data in the SQL tables."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"enrichment-tables","__idx":12},"children":["Enrichment tables"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use the following enrichment tables to help you analyze and get insights into your FHIR data. Some of the tables can also be combined with the views to increase your visibility into your data."]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["enr_rxnconso"]},": Map NCD codes and RX codes. Use with the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vw_mapping_rxnorm_to_ndc"]}," view."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["enr_rxnrel"]},": Map NCD codes and RX codes. Use with the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vw_mapping_rxnorm_to_ndc"]}," view."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["enr_rxnsat"]},": Map NCD codes and RX codes. Use with the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vw_mapping_rxnorm_to_ndc"]}," view."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["enr_valueset"]},": Limited value sets from eCQM (Electronic Quality Measure)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["enr_zip_lat_long"]},": Latitude and longitude values for US ZIP codes. Use to create geographic visualizations."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"fhir-data-tables","__idx":13},"children":["FHIR data tables"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use these FHIR data tables to get more detailed information about your FHIR resource data. Each table contains the information for one type of FHIR resource, which is denoted in the final part of the table name. Within each table, the columns directly map to the attributes defined by the FHIR specification for that resource."]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"FHIR data table"},"children":["FHIR data table"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"FHIR response type"},"children":["FHIR response type"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["fhir_r4.condition"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.hl7.org/fhir/R4/condition.html#resource"},"children":["Condition"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["fhir_r4.coverage"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.hl7.org/fhir/R4/coverage.html#resource"},"children":["Coverage"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["fhir_r4.encounter"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.hl7.org/fhir/R4/encounter.html#resource"},"children":["Encounter"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["fhir_r4.explanationofbenefit"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.hl7.org/fhir/R4/explanationofbenefit.html#resource"},"children":["Explanation of Benefit"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["fhir_r4.observation"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.hl7.org/fhir/R4/observation.html#resource"},"children":["Observation"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["fhir_r4.organization"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.hl7.org/fhir/R4/organization.html#resource"},"children":["Organization"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["fhir_r4.patient"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.hl7.org/fhir/R4/patient.html#resource"},"children":["Patient"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["fhir_r4.practitioner"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.hl7.org/fhir/R4/practitioner.html#resource"},"children":["Practitioner"]}]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"views","__idx":14},"children":["Views"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use the following views to help you evaluate data quality and referential integrity. You can also use them to get view profile information for key FHIR tables, such as Patient, Practitioner, and Explanation of Benefits."]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"View"},"children":["View"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vw_loaded_resources"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Count of resources loaded by day."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vw_ref_int_with_path_and_privclientid_aggr"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Aggregate information on referential integrity among resources. If a FHIR resource contains a reference, this is the count of resources that exist (match) or don’t exist (mismatch)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vw_ref_int_with_path_and_privclientid_details"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Detailed information on referential integrity. Lists all references and whether they exist (match) or don’t exist (mismatch)."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"best-practices","__idx":15},"children":["Best practices"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When you use 1up SQL on FHIR, we recommend that you use the following best practices for writing your SQL queries to use SQL on FHIR. Whether you are familiar with SQL syntax, or new to writing SQL queries, this information is valuable because it describes the specific recommended methods of querying for 1up SQL on FHIR."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["SQL on FHIR is a columnar store. We recommend that you only query the fields that are required for efficient and optimized performance. For more information about columnar storage, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://docs.aws.amazon.com/redshift/latest/dg/c_columnar_storage_disk_mem_mgmnt.html"},"children":["Amazon Redshift's documentation"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"reserved-words","__idx":16},"children":["Reserved words"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Amazon Redshift has a list of ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://docs.aws.amazon.com/redshift/latest/dg/r_pg_keywords.html"},"children":["reserved words"]},". Some of the table fields that you use with SQL on FHIR might coincide with the reserved words. To successfully query the fields without encountering issues, make sure to include double quotes (“ “) around the field name."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"reserved-word-example","__idx":17},"children":["Reserved word example"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"select p.\"language\"\nfrom fhir_r4.patient p \nlimit 10;\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"case-sensitivity","__idx":18},"children":["Case sensitivity"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Some fields in FHIR tables include mixed-case values. To make sure you can successfully query the fields without encountering issues, you can enable the case-sensitive identifier."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"verify-case-sensitivity-status","__idx":19},"children":["Verify case sensitivity status"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"SHOW enable_case_sensitive_identifier;\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"enable-case-sensitivity","__idx":20},"children":["Enable case sensitivity"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"SET enable_case_sensitive_identifier to TRUE;\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"query-mixed-case-fields","__idx":21},"children":["Query mixed-case fields"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["One example of a common mixed-case query is the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["valueCodeableConcept"]}," field in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fhir_r4.observation"]}," table."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"select o.\"valueCodeableConcept\"\nfrom fhir_r4.observation o\nlimit 10;\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"use-super","__idx":22},"children":["Use SUPER"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use the SUPER data type to store semistructured data as values. FHIR data is highly nested. You can use the SUPER data type to more easily store and interact with these complex data types."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"unnest","__idx":23},"children":["Unnest"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A common task in SQL on FHIR is to query array data. SQL on FHIR supports the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["unnest"]}," function, which is used to expand an array into a relation that can be queried."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example, you can query a FHIR table for Practitioner names. The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["name"]}," column in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fhir_r4.practitioner"]}," table is an array of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["structs"]},", which contains a nest array for the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["given"]}," name."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-nested-array-of-structs","__idx":24},"children":["Example nested array of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["structs"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"name: array | struct ->\n  | id:varchar(256)\n  | use:varchar(256)\n  | family:varchar(256)\n  | given: array | varchar(256)\n  | prefix: array | varchar(256)\n  | suffix: array | varchar(256)\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When you write a query for this example, you must consider that ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fhir_r4.practitioner.name"]}," is an array of varying length that contains 0 or more elements. If you query only the first element from the array, you lose all other values that might be present. To get every element in the array, you must use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["unnest"]}," function."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-query-to-get-all-elements-in-the-array-with-unnest","__idx":25},"children":["Example query to get all elements in the array with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["unnest"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"SELECT \n  id,\n  unnested_name.family as \"Last Name\",\n  given as \"First Name\"\nFROM fhir_r4.practitioner as p,\n  p.\"name\" as unnested_name,\n  unnested_name.given as given\nLIMIT 10;\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"use-json-functions","__idx":26},"children":["Use JSON functions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use the following JSON Functions to convert SQL data from one type to another:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["JSON_SERIALIZE"]},": Convert the SUPER data type to the VARCHAR data type."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["JSON_PARSE"]},": Convert the VARCHAR data type to the SUPER data type."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"join-patient-resources","__idx":27},"children":["Join patient resources"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Joins are used to combine records from two or more related using a common identifier. You can use a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["join"]}," to query for a patient and all of that patient’s observations. SQL on FHIR uses local resource identifiers, in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RESOURCE_TYPE/ID"]}," form."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example, an Observation resource contains a reference to a patient with the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Patient/123xyz"]}," resource identifier. The Patient resource uses only the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ID"]}," portion of that reference, which means that before you can use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["join"]}," you must first separate the local resource identifier resource type from the ID."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can separate the local resource identifier with the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["split_part"]}," function in SQL on FHIR. In the Observation FHIR resource, the Patient identifier is found in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["reference"]}," nested attribute of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["subject"]},", which you can call using dot notation."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-split_part-function","__idx":28},"children":["Example ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["split_part"]}," function"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"js","header":{"controls":{"copy":{}}},"source":"split_part(json_serialize(fhir_r4.observation.subject.reference), '/', 2) AS member_id\n","lang":"js"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This function separates the string in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fhir_r4.observation.subject.reference"]}," on the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/"]}," slash character, and returns the second part, which is the ID."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Another function used in this example is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["json_serialize"]},". The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["split_part"]}," function uses ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["varchar"]}," as the first argument. Because ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fhir_f4.observation.subject.reference"]}," is a SUPER data type, you can use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["json_serialize"]}," function to convert it to a VARCHAR data type."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-query-to-get-all-observation-and-patient-data-for-observations-related-to-a-patient","__idx":29},"children":["Example query to get all Observation and Patient data for observations related to a patient"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"SELECT\n  split_part(json_serialize(o.subject.reference), '/', 2) AS member_id\nFROM\n  fhir_r4.observation o\n  INNER JOIN fhir_r4.patient p ON split_part(json_serialize(o.subject.reference), '/', 2) = p.id\nLIMIT 10;\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"example-queries","__idx":30},"children":["Example queries"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use the following example SQL queries to gather common insights about your data. Each query demonstrates the techniques that 1up recommends you use when querying SQL on FHIR, such as unnesting, joining, and correctly pulling data."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["These queries are written to pull data from common customer use cases. In some situations you might find that null values are returned or you might not see any results. The specific data available in your instance of SQL on FHIR varies depending on what data has been ingested into 1upHealth‘s FHIR Server."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"querying-patient-resources","__idx":31},"children":["Querying Patient resources"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use the examples in this section to learn how to query for common patient information and limit a query to a certain cohort of patients."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"count-of-patients-born-after-a-date","__idx":32},"children":["Count of patients born after a date"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use aggregation to count Patient resources for patients born after a certain date. You can use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["to_date"]}," function to specify the date for date fields, such as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["birthdate"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"SELECT DISTINCT count(*)\nFROM fhir_r4.patient\nWHERE birthdate < to_date('1951-12-26', 'yyyy-mm-dd');\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"birth--death-queries","__idx":33},"children":["Birth & death queries"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use the date_add function to find resources relative to a date."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"query-for-patients-born-in-the-last-6-months","__idx":34},"children":["Query for patients born in the last 6 months"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"SELECT DISTINCT\n    p.*\nFROM fhir_r4.patient p \nWHERE \n    p.birthdate > dateadd(MONTH, -6, getdate())\nLIMIT 10;\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"query-for-deceased-patients","__idx":35},"children":["Query for deceased patients"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"SELECT\n  p.*\nFROM \n  fhir_r4.patient p\nWHERE \n  p.deceasedboolean = true OR deceaseddatetime is not null\nLIMIT 10;\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"find-patient-observations","__idx":36},"children":["Find Patient observations"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This query joins a patient resource to their observations and returns the observation’s code and display text."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"WITH observation AS \n(SELECT\n  split_part(json_serialize(o.subject.reference), '/', 2) AS member_id,\n  code_coding_unnested.code AS observation_code,\n  code_coding_unnested.display AS observation_display\nFROM\n  fhir_r4.observation AS o, \n  o.code.coding AS code_coding_unnested\n )\n SELECT \n     member_id, \n     observation_code, \n     observation_display \n FROM observation AS o\n INNER JOIN fhir_r4.patient ON o.member_id = fhir_r4.patient.id\nLIMIT 10;\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"find-vital-signs","__idx":37},"children":["Find vital signs"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Vital signs are stored in patient observations, and can be joined to the patient resource to return the patient’s member ID."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"WITH observation AS (\n    SELECT \n      split_part(json_serialize(o.subject.reference), '/', 2) AS member_id,\n      category_coding_unnested.version AS category_version,\n      category_coding_unnested.code AS category_code,\n      category_coding_unnested.display AS category_display,\n      code_coding_unnested.code AS observation_code,\n      code_coding_unnested.display AS observation_display\n    FROM \n      fhir_r4.observation AS o,\n      o.category AS category_unnested,\n      o.code.coding AS code_coding_unnested,\n      category_unnested.coding AS category_coding_unnested\n)\nSELECT o.*\nFROM observation AS o\nINNER JOIN fhir_r4.patient p ON o.member_id = p.id\nWHERE \n  o.category_display = 'Vital Signs'\nLIMIT 10;\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"find-smoking-status","__idx":38},"children":["Find smoking status"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Smoking status is one type of observation stored in a survey observation category. You can retrieve all surveys from observations and use the smoking_status_display column to get the smoking status."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"with observation as (\n    SELECT\n      distinct split_part(json_serialize(o.subject.reference), '/', 2) AS member_id,\n      category_coding_unnested.display AS category_display,\n      valueCodeableConcept_coding_unnested.code AS smoking_status_code,\n      valueCodeableConcept_coding_unnested.display AS smoking_status_display\n    FROM\n      fhir_r4.observation o,\n      o.category category_unnested,\n      category_unnested.coding category_coding_unnested,\n      o.\"valueCodeableConcept\".coding valueCodeableConcept_coding_unnested \n )\nselect o.* \nfrom observation as o\n  INNER JOIN fhir_r4.patient p ON o.member_id = p.id\nWHERE\n  category_display = 'survey'\nLIMIT 10;\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"query-coverage-resources","__idx":39},"children":["Query Coverage resources"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Coverage resources include data that can help you understand payments."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"find-coverage-data-in-a-date-range","__idx":40},"children":["Find Coverage data in a date range"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Show members that have coverage started or ended within the last 3 months."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Reserved word"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The word ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["end"]}," is a reserved word and must be double-quoted."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"SELECT\n  *\nFROM fhir_r4.coverage\nWHERE \n  (\n    json_serialize(period.start) > dateadd(month, -3, getdate())\n    OR json_serialize(period.\"end\") > dateadd(month, -3, getdate())\n  )\nLIMIT 10;\n","lang":"sql"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"find-duplicates-in-coverage-data","__idx":41},"children":["Find duplicates in Coverage data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can join coverage data to a patient to find any data that overlaps."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sql","header":{"controls":{"copy":{}}},"source":"SELECT \n  count(id) as n, \n  split_part(json_serialize(c.beneficiary.reference), '/', 2) as patient_id,\n  period.start as period_start,\n  period.\"end\" as period_end\nFROM \n  fhir_r4.coverage c\nGROUP BY\n2, 3, 4\nHAVING \n  n > 1\nORDER BY \n  1\n","lang":"sql"},"children":[]}]},"headings":[{"value":"SQL on FHIR","id":"sql-on-fhir","depth":1},{"value":"FHIR Resources","id":"fhir-resources","depth":2},{"value":"FHIR Resource Identifiers","id":"fhir-resource-identifiers","depth":2},{"value":"How FHIR Maps to Relational Data","id":"how-fhir-maps-to-relational-data","depth":2},{"value":"SQL","id":"sql","depth":2},{"value":"Security, Authentication, Authorization & Limits","id":"security-authentication-authorization--limits","depth":2},{"value":"Setup your SQL client","id":"setup-your-sql-client","depth":2},{"value":"Data types","id":"data-types","depth":2},{"value":"Simple data types","id":"simple-data-types","depth":3},{"value":"Complex data types","id":"complex-data-types","depth":3},{"value":"Time and time zones","id":"time-and-time-zones","depth":2},{"value":"Table and view definitions","id":"table-and-view-definitions","depth":2},{"value":"Enrichment tables","id":"enrichment-tables","depth":3},{"value":"FHIR data tables","id":"fhir-data-tables","depth":3},{"value":"Views","id":"views","depth":3},{"value":"Best practices","id":"best-practices","depth":2},{"value":"Reserved words","id":"reserved-words","depth":3},{"value":"Reserved word example","id":"reserved-word-example","depth":4},{"value":"Case sensitivity","id":"case-sensitivity","depth":3},{"value":"Verify case sensitivity status","id":"verify-case-sensitivity-status","depth":4},{"value":"Enable case sensitivity","id":"enable-case-sensitivity","depth":4},{"value":"Query mixed-case fields","id":"query-mixed-case-fields","depth":4},{"value":"Use SUPER","id":"use-super","depth":3},{"value":"Unnest","id":"unnest","depth":3},{"value":"Example nested array of structs","id":"example-nested-array-of-structs","depth":4},{"value":"Example query to get all elements in the array with unnest","id":"example-query-to-get-all-elements-in-the-array-with-unnest","depth":4},{"value":"Use JSON functions","id":"use-json-functions","depth":3},{"value":"Join patient resources","id":"join-patient-resources","depth":3},{"value":"Example split_part function","id":"example-split_part-function","depth":4},{"value":"Example query to get all Observation and Patient data for observations related to a patient","id":"example-query-to-get-all-observation-and-patient-data-for-observations-related-to-a-patient","depth":4},{"value":"Example queries","id":"example-queries","depth":2},{"value":"Querying Patient resources","id":"querying-patient-resources","depth":3},{"value":"Count of patients born after a date","id":"count-of-patients-born-after-a-date","depth":4},{"value":"Birth & death queries","id":"birth--death-queries","depth":4},{"value":"Query for patients born in the last 6 months","id":"query-for-patients-born-in-the-last-6-months","depth":5},{"value":"Query for deceased patients","id":"query-for-deceased-patients","depth":5},{"value":"Find Patient observations","id":"find-patient-observations","depth":4},{"value":"Find vital signs","id":"find-vital-signs","depth":4},{"value":"Find smoking status","id":"find-smoking-status","depth":4},{"value":"Query Coverage resources","id":"query-coverage-resources","depth":3},{"value":"Find Coverage data in a date range","id":"find-coverage-data-in-a-date-range","depth":4},{"value":"Find duplicates in Coverage data","id":"find-duplicates-in-coverage-data","depth":4}],"frontmatter":{"seo":{"title":"SQL on FHIR"}},"lastModified":"2026-04-24T21:01:48.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/platform/sql-on-fhir","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}