Cannot get ConcatRelated function (made by Allen Browne) to work - vba

I am trying to use the ConcatRelated function (made by Allen Browne) in a simple way, but failing! I have looked at many, many Q&As on this site without success.
My Table (CCDS_Countries) has three fields:
Country_ID -- unique identifier (UID) for this Table
CCDS_ID -- UID for another table (CCDS_Data) with a 1-to-many relationship to this Table
Countries -- a field containing "EU", "US", or "UK".
This is sample data:
Country_ID CCDS_ID Countries
1 0 US
2 1 EU
3 1 US
4 1 UK
Here's the output I want to see in a Query:
CCDS_ID Countries
0 US
1 EU, US, UK
Allen Browne's code is saved in the MS Access DB as "Module 2".
My Query has two output fields: [CCDS_ID] and my code:
=SELECT DISTINCT [CCDS_ID], (ConcatRelated("[Countries]", "[CCDS_Countries]", "[Countries]")) FROM [CCDS_Countries];
When I run the query, I get this error message: "The syntax of the subquery in this expression is incorrect. Check the subquery's syntax and enclose the subquery in parentheses".

First of all, cannot have an SQL statement as a textbox ControlSource. If you want to do the concatenation in textbox on form then just call the function: =ConcatRelated(...).
Secondly, WHERE condition criteria is not correct. Have to pass in CCDS_ID from each record so the function will know for which to accumulate related values. In query object, try:
SELECT DISTINCT CCDS_ID,
ConcatRelated("Countries","CCDS_Countries","[CCDS_ID]=" & [CCDS_ID]) AS Countries
FROM CCDS_Countries;
Alternative query which might perform faster:
SELECT UID,
ConcatRelated("Countries","CCDS_Countries","[CCDS_ID]=" & [UID]) AS Countries
FROM CCDS_Data;
If you want to do concatenation in textbox on form or report that is bound to CCDS_Data table:
=ConcatRelated("Countries","CCDS_Countries","[CCDS_ID]=" & [UID])

The outcome is as expected when the code is pasted into "SQL View" it works as expected. I was putting the code into the "Design View" using the expression builder.

Related

SQL query find few strings in diferent columns in a table row (restrictive)

I have a table like this one (in a SQL SERVER):
field_name
field_descriptor
tag1
tag2
tag3
tag4
tag5
house
your home
home
house
null
null
null
car
first car
car
wheel
null
null
null
...
...
...
...
...
...
...
I'm developing a WIKI with a searchbar, which should be able to handle a query with more than one string for search. As an user enters a second string (spaced) the query should be able to return results that match restrictively the two strings (if exists) in any column, and so with a three string search.
Easy to do for one string with a simple SELECT with ORs.
Tried in the fronted in JS with libraries like match-sorter but it's heavy with a table with more than 100,000 results and more in the future.
I thought the query should do the heavy work, but maybe there is no simple way doing it.
Thanks in advance!
Tried to do the heavy work with all results in frontend with filtering and other libraries like match-sorter. Works but take several seconds and blocks the front.
Tried to create a simple OR/AND query but the posibilities with 3 search-strings (could be 1, 2 or 3) matching any column to any other possibility is overwhelming.
You can use STRING_SPLIT to get a separate row per search word from the search words string. Then only select rows where all search words have a match.
The query should look like this:
select *
from mytable t
where exists
(
select null
from (select value from string_split(#search, ' ')) search
having min(case when search.value in (t.tag1, t.tag2, t.tag3, t.tag4, t.tag5) then 1 else 0 end) = 1
);
Unfortunately, SQL Server seems to have a flaw (or even a bug) here and reports:
Msg 8124 Level 16 State 1 Line 8
Multiple columns are specified in an aggregated expression containing an outer reference. If an expression being aggregated contains an outer reference, then that outer reference must be the only column referenced in the expression.
Demo: https://dbfiddle.uk/kNL1PVOZ
I don't have more time at hand right now, so you may use this query as a starting point to get the final query.

Two queries work separately. Errors when combined. How do I combine two SELECT statements in Libreoffice Base?

I've reached a point with a spreadsheet where it is no longer viable to keep data in that format. I've created a table in Libreoffice Base with the relevant information and I'm trying to put together some queries. Unfortunately, my attempts to create a SQL query are so far being met with syntax errors. To be expected, given it's all new to me.
Here's my example table:
TINYINT-A
TINYINT-B
NUMERIC-A
NUMERIC-B
BOOLEAN-A
BOOLEAN-B
1
2
100
200
1
0
9
8
900
800
0
1
I have the following query running fine:
SELECT
SUM("TINYINT-A") AS "First Column",
SUM("TINYINT-B") AS "Second Column",
SUM("NUMERIC-A") AS "Third Column",
SUM("NUMERIC-B") AS "Fourth Column"
FROM
"Table-A"
Output would be:
First Column
Second Column
Third Column
Fourth Column
10
10
1000
1000
I would like to add a fifth column which sums up the rows in one of the previous four column when the boolean value is equal to 1 or 0. As a separate query, I can do this:
SELECT
SUM("NUMERIC-A") AS "BOOLEAN-A-NUMERIC-A",
SUM("NUMERIC-B") AS "BOOLEAN-A-NUMERIC-B"
FROM
"Table-A"
WHERE
"BOOLEAN-A" = 1
Expected output:
BOOLEAN-A-NUMERIC-A
BOOLEAN-A-NUMERIC-B
100
200
However, if I try to put the two into one query so that the output above is tacked on to the end of the first output, I get a syntax error. This is my attempt at combining the two:
SELECT
(
SELECT
SUM("TINYINT-A") AS "First Column",
SUM("TINYINT-B") AS "Second Column",
SUM("NUMERIC-A") AS "Third Column",
SUM("NUMERIC-B") AS "Fourth Column"
FROM
"Table-A"
),
(
SELECT
SUM("NUMERIC-A") AS "BOOLEAN-A-NUMERIC-A",
SUM("NUMERIC-B") AS "BOOLEAN-A-NUMERIC-B"
FROM
"Table-A"
WHERE
"BOOLEAN-A" = 1
)
FROM
"Table-A"
I forgot which SO question I tried to derive the structure of the above from, but it clearly didn't work, so either I didn't understand it correctly, or I have left out a character somewhere.
I also attempted to take the two separate queries exactly as they are, and put a new line between them with just UNION. This results in an error stating that the given command is not a SELECT statement. I'm guessing because the two statements don't have the same output structure.
I'm not even sure if the commands are the same in Base, and whether things vary significantly enough between other databases such as MySQL. I'm sure they are, and that I'm probably just doing something comparable to attempting to execute Python using HTML tags/syntax or something.
I don't know libreoffice and use Postgres, but maybe it works the same way and you can get an idea of it.
Given:
CREATE TABLE Table_A (
TINYINT_A SMALLINT,
TINYINT_B SMALLINT,
NUMERIC_A NUMERIC,
NUMERIC_B NUMERIC,
BOOLEAN_A BOOLEAN,
BOOLEAN_B BOOLEAN
);
INSERT INTO Table_A (
TINYINT_A,
TINYINT_B,
NUMERIC_A,
NUMERIC_B,
BOOLEAN_A,
BOOLEAN_B
)
VALUES
(1,2,100,200,true,false),
(9,8,900,800,false,true);
in postgres it works with subqueries like this, although I'm sure, there are better solutions:
SELECT
SUM(TINYINT_A) AS "First Column",
SUM(TINYINT_B) AS "Second Column",
SUM(NUMERIC_A) AS "Third Column",
SUM(NUMERIC_B) AS "Fourth Column",
(SELECT SUM(NUMERIC_A) FROM Table_A WHERE BOOLEAN_A is true) AS BOOLEAN_A_NUMERIC_A,
(SELECT SUM(NUMERIC_B) FROM Table_A WHERE BOOLEAN_A is true) AS BOOLEAN_A_NUMERIC_B
FROM Table_A

MS Access: Selecting Records from 2 Tables Without Foreign Key

I'm tracking my driving habits in MS Access 2016. I have a table called Miles:
In my Miles table, I'm recording information from my car's dash at the end of each drive.
I also have a 2nd table (actually a query) called Fuel:
My Fuel query shows when I purchased fuel and for how much.
I want to create a query that shows that shows the greatest Transaction_Date that is less than or equal to each Miles_Date. My expected output would look something like this:
I tried the following Select statement:
SELECT
Miles.Miles_ID,
DMax("[Transaction_Date]", "Fuel", "[Fuel]![Transaction_Date] <= [Miles]![Miles_Date]") AS Fuel_Date,
Miles.Miles_Date, Miles.Miles, Miles.MPG
FROM
Miles;
I get the error:
Microsoft Access cannot find the name [Miles]![Miles_Date]
When using a domain aggregate, you need to use string concatenation to pass values from the current row, like this:
SELECT
Miles.Miles_ID,
DMax("[Transaction_Date]", "Fuel", "[Fuel].[Transaction_Date] <= #" & Format(Miles.Miles_Date, "yyyy-mm-dd") & "#") AS Fuel_Date,
Miles.Miles_Date, Miles.Miles, Miles.MPG
FROM
Miles;
However, using a domain aggregate in a query is a bad practice, since it limits the influence of the optimizer. When possible, use a subquery instead:
SELECT
Miles.Miles_ID,
(SELECT Max([Transaction_Date]) FROM Fuel WHERE [Fuel].[Transaction_Date] <= Miles.Miles_Date) AS Fuel_Date,
Miles.Miles_Date, Miles.Miles, Miles.MPG
FROM
Miles;
This will both run faster, and not rely on string concatenation.

Selecting only such groups that contain certain value

First of all, even though this SQL: How do you select only groups that do not contain a certain value? thread is almost identical to my problem, it doesn't fully dissipate my confusion about the problem.
Let's have a table "Contacts" like this one:
+----------------------+
| Department FirstName |
+----------------------+
| 100 Thomas |
| 200 Peter |
| 100 Jerry |
+----------------------+
First, I want to group the rows by the department number and show number of rows in each displayed group. This, I believe, can be easily done by the following query.
SELECT Department, Count(*) As "Rows_in_group"
FROM Contacts
GROUP BY Department
This outputs 2 groups. First with dep.no. 100 containing 2 rows, second with 200 containing only one row.
But then, I want to extend the query to exclude any group that doesn't contain certain value in certain column (e.g. Thomas in FirstName). Here are my questions:
1) Reading the above-mentioned thread I was able to come up with this, which seems to work correctly:
SELECT Department, Count(*) As "Rows_in_group"
FROM Contacts
WHERE Department IN (SELECT Department FROM Contacts WHERE FirstName = "Thomas")
GROUP BY Department
Q: How does this work? I understand the "WHERE Department IN" part, but then I'd expect a value, but instead another nested query is included, which to me doesn't make much sense as I'm only beginner with SQL.
2) By accident I was able to come up with another query that also seems to work, but feels weird and I also don't understand its workings.
SELECT Department, Count(*) As "Rows_in_group"
FROM Contacts
GROUP BY Department
HAVING NOT SUM(FirstName = "Thomas") = 0
Q: How does this work? Why alteration: HAVING SUM(FirstName = "Thomas") > 0 doesn't work?
3) Q: Is there any simple and correct way to do this using the HAVING clause?
I expected, that simple "HAVING FirstName='Thomas'" after the GROUP BY would do the trick as it seems to follow a common language, but it does not.
Note that I want the whole groups to be chosen by the query so "WHERE FirstName='Thomas'" isn't s solution for my problem as it excludes all the rows that don't satisfy the condition before the grouping takes place (at least the way I understand it).
Q: How does this work? I understand the "WHERE Department IN" part,
but then I'd expect a value, but instead another nested query is
included, which to me doesn't make much sense as I'm only beginner
with SQL.
The nested query returns values which are used to match against Department
2) By accident I was able to come up with another query that also
seems to work, but feels weird and I also don't understand its
workings.
HAVING NOT SUM(FirstName = "Thomas") = 0
"Feels weird" because, well, it is. This is not a place for the SUM function.
EDIT: Why does this work?
The expression FirstName = "Thomas" gets evaluated as true or false (known as a Boolean expression). True numerically is equal to 1 and False converts to 0 (zero). By including SUM you then calculated the totals so really zero (still) means false and "not zero" is true. Then to make it weird(er) you included NOT which negated the whole thing and it becomes NOT TRUE = 0 or FALSE = FALSE (which is of course... TRUE)!!
EDIT: I think what could be more helpful to you is consideration of when to use WHERE and when to use HAVING (instead of the Boolean magic taking place).
From this answer:
WHERE clause introduces a condition on individual rows; HAVING clause introduces a condition on aggregations, i.e. results of selection where a single result, such as count, average, min, max, or sum, has been produced from multiple rows.
WHERE was appropriate for your example because first you want to "only return rows WHERE Department IN (100)" and then you want to "group those rows by Department" and get a COUNT of how many rows had been selected.

SQL Query in Access with YesNo field Returns No Results

I am learning to use SQL in Access 2013 and things are going well, but I'm having some trouble with one of the objectives of the assignment. First of all, here is the table information that I need to consider:
Field Name Data Type
StudentID Short Text
FirstName ""
MiddleInitial ""
LastName ""
DateofBirth Date/Time
GradePointAverage Number
Major Short Text
CreditsEarned Number
Probation Yes/No
USCitizen Yes/No
Class Short Text
What I need to do is determine the students on Probation who are not US Citizens. Following is my SQL Query Code:
SELECT StudentID, LastName, FirstName, Major, Probation, USCitizen
FROM Student
WHERE Probation = 1
AND USCitizen = 0;
There is one record on the Student table that should show up as a result when I run this query, but the query is blank instead, showing the column names but with no rows of data. This is just one aspect of a larger assignment and while I'm not having any difficulty with the other objectives, this one is stumping me. Why is it not returning the one row result? What am I doing wrong here?
From Microsoft Access Data Types on W3schools, can you try comparing to -1 rather than 1:
A logical field can be displayed as Yes/No, True/False, or On/Off. In code, use the constants True and False (equivalent to -1 and 0). Note: Null values are not allowed in Yes/No fields.
Sorry, don't have a copy of access handy to try this out.