It’s not trivial to both get the overall total, and also the total of a given case within the same table. I tend sometimes to use dataviewjs to do this, but there are at least two other options, which I’ll explore below:
Using filter
and GROUP BY true
You’ve presented queries which are able to calculate each of the totals, and you could’ve expanded the one getting the overall total, to do a filter
counting only the valid test cases within the resulting rows.
However when you’re using containsword()
to check you need to be aware that this function works different when presented with a list versus a string. See its documentation.
One query to do this using that function would be to do:
```dataview
TABLE WITHOUT ID
totalCount, posCount, negCount, rows.testCase
FROM "ForumStuff/f69/f69984"
WHERE subject
FLATTEN any(containsword(subject, "first")) as testCase
GROUP BY true
FLATTEN length(rows) as totalCount
FLATTEN length(filter(rows.testCase, (r) => r)) as posCount
FLATTEN length(filter(rows.testCase, (r) => !r)) as negCount
```
Note that my queries use the FROM "ForumStuff/..."
and tests the subject
for first
, instead of your examples, so you need to change those to match your case.
Another option with the same kind of result would be to use contains()
:
TABLE WITHOUT ID
totalCount, posCount, negCount
FROM "ForumStuff/f69/f69984"
WHERE subject
GROUP BY true
FLATTEN length(rows) as totalCount
FLATTEN length(filter(rows.subject, (r) => contains(r, "first") )) as posCount
FLATTEN length(filter(rows.subject, (r) => !contains(r, "first") )) as negCount
This latter one would possibly be easier to use if you wanted to test for multiple cases, but it kind of depends on preferences.
Using dual GROUP BY
statements
Yet another variant would be to use dual GROUP BY
statements. By this I mean that we first do a query listing all rows to be included in the statistics, preferably with extra variables (by using FLATTEN
) denoting the various test cases.
Ignoring the first line, which is heavily impacted by later statements, we could imagine this to look like:
TABLE count, round(count / total, 2) as Ratio
FROM "ForumStuff/f69/f69984"
WHERE subject
FLATTEN any(containsword(subject, "first")) as testCase
Same caveats as before regarding the folder, subject and text to match for.
On this overall query we do the first group by to gives us the total number of rows in our test set, and then we proceed to split this set into groups for each test case.
GROUP BY true
FLATTEN length(rows) as totalCount
FLATTEN rows.testCase as case
Finally we group by each test case, and do some final calculation and beautifications on our variables, to allow for the first line (with TABLE
) to be manageable and readable:
GROUP BY case
FLATTEN length(rows) as count
FLATTEN rows.totalCount[0] as total
Gather all of these pieces back into one query, and you should be good to go with one row for each of the test cases. An untested version corrected back to your environment should look something like:
```dataview
TABLE count, round(count / total, 2) as Ratio
FROM "Folder"
WHERE reviewtags
FLATTEN any(containsword(reviewtags, "early")) as testCase
GROUP BY true
FLATTEN length(rows) as totalCount
FLATTEN rows.testCase as case
GROUP BY case
FLATTEN length(rows) as count
FLATTEN rows.totalCount[0] as total
```