Using SQL Views with Generic Inquiries and Reports in Acumatica
Generic Inquiries are one of Acumatica's most powerful features. They allow users to create custom queries and reports without extensive programming skills. But what happens when your query becomes too complex for the standard GI builder? Or when performance suffers due to large datasets and multiple joins? That's where SQL Views come in.
The best part? Once you create a SQL View, you can use it in both Generic Inquiries and Acumatica Reports—giving you a single source of truth for complex data across your entire reporting ecosystem.
⚡ Key Insight: SQL Views are not a replacement for Generic Inquiries—they are an enhancement that extends what GIs can do. When you need advanced logic or better performance, SQL Views are the answer. And they work seamlessly with Acumatica Reports too.
When to Use SQL Views Instead of Generic Inquiries
Generic Inquiries are great for most scenarios. However, there are specific situations where a SQL View is a better choice:
- Complex Business Logic: When your condition cannot be expressed using the GI's Condition tab. For example, counting how many fields are filled in a record across multiple columns
- SELECT DISTINCT Functionality: Generic Inquiries do not support SELECT DISTINCT. A SQL View can handle this requirement
- Performance Issues: When your GI has many joins and is slowing down the system
- Large Datasets: When you're working with high-volume data and need to push the processing to the database layer for better performance
- Complex Aggregations: When you need to perform calculations that are cumbersome in GIs
💡 Pro Tip: Many developers report 4-5 times faster results by creating SQL Views and using them as corresponding DACs in Acumatica instead of doing all the joins in GIs.
Why SQL Views Are a Unified Solution
Acumatica's reporting and Generic Inquiry systems both rely on DACs (Data Access Classes). When you create a SQL View and map it to a DAC, that DAC becomes available in both Generic Inquiries and the Report Designer. This means:
- One View, Multiple Use Cases: Create the complex logic once in a SQL View, then use it across your entire reporting ecosystem
- Consistent Data: Both GIs and reports pull from the same data source, ensuring consistency
- Reduced Maintenance: Update the view in one place, and all dependent GIs and reports are automatically updated
- Better Performance: The complex processing happens at the database level, benefiting both GIs and reports
Step-by-Step Guide: Creating and Using SQL Views
Step 1: Create the SQL View
Start by creating your SQL View. Here's a sample that summarizes sales order data for better reporting performance:
CREATE OR ALTER VIEW dbo.MySalesOrderInfo AS
SELECT
OrderType,
OrderNbr,
COUNT(*) AS '# of lines',
SUM(ExtPrice) AS 'Total Amount',
MIN(ExtPrice) AS 'Minimum Amount',
MAX(ExtPrice) AS 'Maximum Amount'
FROM SOLine
GROUP BY OrderType, OrderNbr
Here's another example that counts how many fields are filled for each contact—a complex condition that's difficult to achieve in a GI directly:
CREATE VIEW ContactsWithMinFields AS
SELECT
ContactID,
Field1, Field2, Field3, Field4, Field5,
Field6, Field7, Field8, Field9,
(CASE WHEN Field1 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field2 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field3 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field4 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field5 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field6 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field7 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field8 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field9 IS NOT NULL THEN 1 ELSE 0 END) AS FieldsFilled
FROM Contact
WHERE (CASE WHEN Field1 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field2 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field3 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field4 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field5 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field6 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field7 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field8 IS NOT NULL THEN 1 ELSE 0 END +
CASE WHEN Field9 IS NOT NULL THEN 1 ELSE 0 END) >= 3
Step 2: Add the SQL View to Your Customization Project
- Open the Customization Project Editor
- Add the SQL View script to the Database Scripts section. This ensures the view is created when the customization is published
- Publish the customization to create the view in the database
⚠️ Important: Always add the Database Script first and publish it before creating the DAC. If you create the DAC first, the system will complain that the object doesn't exist.
Step 3: Create the DAC
After publishing the view, create a Data Access Class (DAC) that maps to your SQL View:
- In the Customization Project Editor, click the plus (+) button to add a new object
- Select New DAC as the File Template
- Enter the name of your View as the class name (must match the view name exactly)
- Check the box to Generate Members from Database. This will automatically create a code file that maps to all the fields in your view
using System;
using PX.Data;
namespace MyCustomViews
{
[Serializable]
[PXCacheName("MySalesOrderInfo")]
public class MySalesOrderInfo : IBqlTable
{
// Fields will be auto-generated by Acumatica
// when you check "Generate Members from Database"
}
}
Step 4: Publish and Use in Generic Inquiries
After publishing the customization, your SQL View is now available as a DAC and can be used in Generic Inquiries:
- Open the Generic Inquiry (SM208000) form
- Create a new inquiry and select your new DAC as a data source
- Add the fields you need to the Results Grid
- Save and view your inquiry
Step 5: Use in Acumatica Reports
The same DAC is now available in the Report Designer:
- Open the Report Designer (SM208060)
- Create a new report or edit an existing one
- In the Data Source section, select your new DAC
- Add the fields to your report design
- Save and preview your report
💡 Pro Tip: By using the same DAC, you ensure that your Generic Inquiries and Reports are always in sync. Any changes to the SQL View automatically reflect in both tools.
Why This Approach Works
✅ Single Source of Truth
The same complex logic is used for both GIs and reports, eliminating inconsistencies.
✅ Reduced Maintenance
Update the view once, and all dependent GIs and reports are automatically updated.
✅ Better Performance
Complex processing happens at the database level, benefiting both GIs and reports.
✅ Consistent Results
Whether users access data via GI or report, they see the same results.
Common Use Cases for SQL Views
1. Count-Based Conditions
When you need to check if a certain number of fields are filled (like "at least 3 of 9 fields must have values"), this logic is difficult in GIs but simple in SQL Views.
2. SELECT DISTINCT
Generic Inquiries don't support SELECT DISTINCT. A SQL View solves this problem.
3. Complex Aggregations
When you need to calculate totals, averages, or other aggregations across multiple tables, SQL Views can handle these efficiently.
4. Nested Generic Inquiries
For very complex queries, you can use Generic Inquiries as Data Sources for other Generic Inquiries, but SQL Views often provide better performance for the most complex scenarios.
Important Considerations
- Direct Database Access: Direct access bypasses security measures and increases data corruption risk. Use PXDatabase class for safe interactions
- Acumatica Recommended Approach: While SQL Views are not Acumatica's suggested approach for all scenarios, they are acceptable for performance optimization
- Security: Ensure your SQL Views respect Acumatica's security model. Role-based access should still be enforced
- Maintenance: SQL Views need to be maintained alongside your customization projects. Document them clearly
⚠️ Warning: Direct database access is highly discouraged in Acumatica. Always use the framework's built-in methods (PXDatabase, DACs) for data operations to maintain security and upgrade compatibility.
Performance Optimization Best Practices
✅ Use SQL Views for Performance
For high-volume scenarios, pushing the load to the database layer significantly improves performance.
✅ Avoid Unnecessary Joins in GIs
A GI with many joins can cause performance issues. Consider moving complex joins to a SQL View.
✅ Consider Stored Procedures for Scheduled Reports
For heavy calculations that don't require live data, use stored procedures scheduled to run overnight.
✅ Monitor Dashboard Refresh Rates
Complex GIs in dashboards can cause constant refreshing. Optimize them to avoid user impact.
Conclusion
SQL Views are a powerful enhancement to Acumatica's Generic Inquiry and Reporting capabilities. They allow you to:
- Handle complex business logic that's difficult in GIs
- Improve performance for large datasets
- Perform SELECT DISTINCT operations
- Create complex aggregations efficiently
- Use the same view in both Generic Inquiries and Reports
By leveraging SQL Views, you create a unified data source that works across Acumatica's entire reporting ecosystem, ensuring consistency and reducing maintenance overhead.
📌 Key Takeaway: SQL Views are not a replacement for Generic Inquiries—they are an enhancement. Use them when you need advanced logic or better performance. With proper implementation, they can deliver 4-5 times faster results while maintaining the flexibility of Generic Inquiries and Reports.
🔍 Further Reading: Explore Acumatica's official documentation on Generic Inquiries, DAC creation, and Report Designer. The Acumatica Developer Network provides comprehensive resources for advanced reporting scenarios.