A household membership with two adults and a nanny add-on can easily carry three or four card names. Pull that membership into an Altru query, add the card name as an output field, and the result suddenly has three or four rows for what you think of as one membership. Counts look inflated, mailing lists double up, and anyone who exports it to a spreadsheet starts deleting rows by hand.
None of that means the query is broken. It means the card name lives at a different level than the membership, and the query is doing exactly what it was asked. The fix depends on which list you actually need.
Why one membership turns into several rows
In Altru, a membership is one record, but the people on it (the members) and the cards issued to them sit underneath it as a one-to-many relationship. When a membership query outputs only membership-level fields, such as program, level, expiration date, or primary member, you get one row per membership. The moment you add any field from the members or cards section, the query has to return one row for each matching member or card, and the membership-level columns repeat on every row.
Keep that rule in mind and most of the confusion goes away: every output field from a one-to-many area multiplies the rows. Add card name and member name together and you may multiply them again, depending on how the two relate in your data.
Decide which result you want
“Memberships with multiple card names” usually means one of three different lists. Build the one you need rather than trying to make a single query do all three.
1. A list of every card name, one per row
This is the easiest case and the default behavior. Start from the membership source view, add your filters (active memberships, a specific program or level, an expiration range), then add the card name field from the cards area. Include the membership ID or lookup ID as an output column so you can tell which rows belong together. Sort by that ID.
This version is right for printing cards, checking spelling, or handing the front desk a list of who is allowed to use each membership.
2. Only memberships that have more than one card name
Here you want to filter, not just display. Two approaches work, depending on what your query designer offers:
- Filter on a count. Look in the membership source view for a count-style field covering members or cards. If one exists, filter where it is greater than one. If you are not sure whether a given field counts cards or members, test it against a couple of memberships you know well before relying on it.
- Use a smart field. If your organization has a smart field that counts members or cards on a membership, it can serve as a filter on the membership query. Smart fields are calculated on a schedule, so the count can lag recent changes until the next refresh.
If neither option is available in your database, fall back to the row-per-card version from section 1, export it, and count rows per membership ID in a spreadsheet. It is less elegant, but it is reliable and easy to check.
3. One row per membership with all card names side by side
This is the one people usually mean, and it is the hardest to get natively. Ad-hoc queries are good at returning rows, not at combining several child rows into one cell. Whether your version of Altru offers a way to concatenate or pivot child values within a query is something to confirm with Blackbaud support or by testing in a sandbox; we would not assume it.
The dependable route is to run the row-per-card query and combine the names after export:
- Export the query with membership ID, the membership-level fields you need, and card name.
- In Excel or Google Sheets, build a list of unique membership IDs.
- Next to each ID, use a formula that joins every card name for that ID. In current versions of both tools,
TEXTJOINcombined withFILTERdoes this in one cell, separated by a comma or line break. - Pull the membership-level columns in with a lookup on the ID.
Save the spreadsheet as a template so next month’s version is a paste and a refresh, not a rebuild.
Things that trip people up
- Card name and member name are not always the same. A card can be printed with a nickname or a different spelling than the constituent record. Decide which one your list should show, and do not mix fields from both areas unless you need the comparison.
- Old cards may still be in the data. Reissued or replaced cards can leave earlier card rows behind. If you see the same person twice with slightly different names, check whether you need a filter on card status or issue date. Review the available card fields in your query designer to see what you can filter on.
- Lapsed memberships sneak in. Filter on membership status or expiration date first, before adding card fields, so you can confirm the membership count is right before rows multiply.
- Check the total against a known number. Run the membership-only version and note the count. After adding card fields, the number of distinct membership IDs in the output should match it. If it does not, a filter on the card area is dropping memberships that have no card yet.
Keeping the combined list current
The export-and-combine step is fine once a quarter. If staff need the combined view every week, the manual export becomes the bottleneck. Data Bridge syncs Altru query results to Google Sheets and other tools, so the row-per-card query can land in a sheet automatically and the TEXTJOIN formulas recalculate without anyone exporting a file.
Quick answers
Why did my membership count double when I added card name?
Card name comes from a one-to-many area under the membership, so the query returns one row per card. Count distinct membership IDs instead of rows.
Can I show only the primary member’s card?
Often, yes, if your query designer exposes a primary-member or member-role field you can filter on. Test it on a household membership to confirm it returns the card you expect.



