Skip to content

SELECT Queries

Syntra ODBC supports standard SQL SELECT syntax for reading QuickBooks data. Queries run against the local cache by default, with the option to force live fetches from QuickBooks.

SELECT * FROM customers;
SELECT name, phone, email, balance
FROM customers;

Filter rows using standard comparison operators:

SELECT name, balance
FROM customers
WHERE balance > 1000;
SELECT * FROM invoices
WHERE txn_date >= '2025-01-01'
AND is_paid = false;
SELECT * FROM item_inventories
WHERE name ILIKE '%widget%';
OperatorExample
=, !=, <>WHERE is_active = true
<, >, <=, >=WHERE balance >= 500
LIKE / ILIKEWHERE name ILIKE '%corp%'
INWHERE ref_number IN ('INV-001', 'INV-002')
BETWEENWHERE txn_date BETWEEN '2025-01-01' AND '2025-12-31'
IS NULL / IS NOT NULLWHERE email IS NOT NULL
AND, OR, NOTWHERE balance > 0 AND is_active = true

Sort results by one or more columns:

SELECT name, balance
FROM customers
ORDER BY balance DESC;
SELECT * FROM invoices
ORDER BY txn_date DESC, ref_number ASC;

Restrict the number of returned rows:

SELECT * FROM customers
ORDER BY name
LIMIT 50;
SELECT * FROM customers
ORDER BY name
LIMIT 50 OFFSET 100;

Use aggregate functions with GROUP BY:

SELECT customer_ref_full_name, COUNT(*) AS invoice_count, SUM(balance_remaining) AS total_owed
FROM invoices
GROUP BY customer_ref_full_name
ORDER BY total_owed DESC;
  • COUNT(*), COUNT(column), COUNT(DISTINCT column)
  • SUM(column)
  • AVG(column)
  • MIN(column), MAX(column)
-- Total customers
SELECT COUNT(*) AS total_customers FROM customers;
-- Invoice totals
SELECT SUM(subtotal) AS total, AVG(subtotal) AS average FROM invoices;
-- Revenue by customer
SELECT
customer_ref_full_name,
COUNT(*) AS invoice_count,
SUM(subtotal) AS revenue,
AVG(subtotal) AS avg_invoice
FROM invoices
GROUP BY customer_ref_full_name
ORDER BY revenue DESC;
-- Monthly invoice summary
SELECT
DATE_TRUNC('month', txn_date) AS month,
COUNT(*) AS invoices,
SUM(subtotal) AS total
FROM invoices
GROUP BY month
ORDER BY month;

Filter groups after aggregation:

SELECT customer_ref_full_name, SUM(balance_remaining) AS total_owed
FROM invoices
GROUP BY customer_ref_full_name
HAVING SUM(balance_remaining) > 5000
ORDER BY total_owed DESC;
SELECT
name AS "Customer",
balance AS "Amount Owed",
phone AS "Phone Number"
FROM customers;

Remove duplicate rows:

SELECT DISTINCT customer_ref_full_name
FROM invoices
WHERE txn_date >= '2025-01-01';
SELECT
name,
balance,
CASE
WHEN balance = 0 THEN 'Paid'
WHEN balance < 1000 THEN 'Low'
ELSE 'High'
END AS balance_category
FROM customers;

Every column returned by a query has a Syntra SQL type with a numeric type code. You can inspect column types using the Query Explorer’s hover tooltips (hover over any column header) or the Copy Schema JSON button. See the Syntra SQL Type Reference for what each code means.

Running SELECT list_id, name, full_name, email, phone, balance FROM customers LIMIT 5 and clicking Copy Schema JSON produces:

[
{ "name": "list_id", "type": "varchar", "oid": 1043 },
{ "name": "name", "type": "varchar", "oid": 1043 },
{ "name": "full_name", "type": "varchar", "oid": 1043 },
{ "name": "email", "type": "varchar", "oid": 1043 },
{ "name": "phone", "type": "varchar", "oid": 1043 },
{ "name": "balance", "type": "numeric", "oid": 1700 }
]

Syntra ODBC maps QuickBooks field types to standard PostgreSQL types:

OIDPG TypeDescriptionQuickBooks Examples
1043varcharVariable-length stringNames, IDs, addresses, memos
1700numericDecimal with precision/scaleBalance, subtotal, rate, amount
23int432-bit integerTxnNumber, counts
20int864-bit integerCOUNT(*) results
16boolBoolean (true/false)IsActive, IsPaid, IsPending
1082dateCalendar dateTxnDate, DueDate, ShipDate
1114timestampDate + timeTimeCreated, TimeModified

You can also query column metadata directly via SQL:

-- List all columns for a table
SHOW COLUMNS FROM customers;
-- Detailed column info via information_schema
SELECT column_name, data_type, ordinal_position
FROM information_schema.columns
WHERE table_name = 'invoices'
ORDER BY ordinal_position;
-- Column metadata via pg_catalog (includes type OIDs)
SELECT attname, typname, atttypid
FROM pg_catalog.pg_attribute a
JOIN pg_catalog.pg_class c ON true
WHERE c.relname = 'customers';

Syntra ODBC exposes 121 QuickBooks tables. Here are the most commonly queried:

TableKey ColumnDescription
customerslist_idCustomer records with contact info and balance
invoicestxn_idSales invoices
invoice_linestxn_line_idLine items on invoices (linked by txn_id)
credit_memostxn_idCredit memos
estimatestxn_idEstimates / quotes
sales_receiptstxn_idSales receipts (immediate payment)
sales_orderstxn_idSales orders
receive_paymentstxn_idPayments received
TableKey ColumnDescription
vendorslist_idVendor records
billstxn_idBills from vendors
purchase_orderstxn_idPurchase orders
bill_payment_checkstxn_idBill payments by check
bill_payment_credit_cardstxn_idBill payments by credit card
TableKey ColumnDescription
item_inventorieslist_idInventory items with quantity on hand
item_non_inventorieslist_idNon-inventory items
item_serviceslist_idService items
item_other_chargeslist_idOther charge items
item_discountslist_idDiscount items
item_groupslist_idGroup items
item_sales_taxeslist_idSales tax items
TableKey ColumnDescription
accountslist_idChart of accounts
checkstxn_idChecks written
depositstxn_idBank deposits
journal_entriestxn_idJournal entries
currencieslist_idCurrency definitions
TableKey ColumnDescription
classeslist_idClass tracking categories
employeeslist_idEmployee records
payment_methodslist_idPayment method types
ship_methodslist_idShipping methods
customer_typeslist_idCustomer type categories
vendor_typeslist_idVendor type categories
sales_tax_codeslist_idSales tax codes

Use SHOW TABLES; to see the complete list of all 121 tables.

SELECT
c.full_name,
c.balance,
COUNT(i.txn_id) AS open_invoices,
MIN(i.txn_date) AS oldest_invoice,
MAX(i.txn_date) AS newest_invoice
FROM customers c
LEFT JOIN invoices i ON i.customer_ref_list_id = c.list_id AND i.is_paid = false
WHERE c.balance > 0
GROUP BY c.full_name, c.balance
ORDER BY c.balance DESC;
SELECT
il.item_ref_full_name,
COUNT(*) AS times_sold,
SUM(il.quantity) AS total_qty,
SUM(il.amount) AS total_revenue
FROM invoice_lines il
GROUP BY il.item_ref_full_name
ORDER BY total_revenue DESC
LIMIT 20;
SELECT
i.ref_number,
i.txn_date,
i.due_date,
c.full_name,
c.phone,
i.balance_remaining
FROM invoices i
INNER JOIN customers c ON i.customer_ref_list_id = c.list_id
WHERE i.is_paid = false AND i.balance_remaining > 0
ORDER BY i.due_date ASC;
SELECT
DATE_TRUNC('month', txn_date) AS month,
COUNT(*) AS invoice_count,
SUM(subtotal) AS gross_revenue,
SUM(sales_tax_total) AS tax_collected,
SUM(balance_remaining) AS outstanding
FROM invoices
WHERE txn_date >= '2025-01-01'
GROUP BY month
ORDER BY month;
SELECT
full_name,
quantity_on_hand,
average_cost,
quantity_on_hand * average_cost AS total_value
FROM item_inventories
WHERE is_active = true AND quantity_on_hand > 0
ORDER BY total_value DESC;

By default, SELECT queries read from the local cache. To force a live fetch from QuickBooks:

SET QB_MAX_STALENESS = 0;
SELECT * FROM customers WHERE list_id = '80000001-1234567890';

See Special Commands for more details on cache control.