My MS Access query is too complex - ms-access

I've recently created a large MS Access database and i'm trying to build some logic into it. However I get an error message saying the query is too complex. After doing some debugging it seems like 4 switch statements work fine but more then 6 cause a problem (example below). My version has 100+ statements and should add an extra column based on the value in HOSTNAMEDB.NAME.
Example
SELECT
...
SWITCH (
HOSTNAMEDB.NAME LIKE "serverA*", "Customer A",
HOSTNAMEDB.NAME LIKE "serverB*", "Customer B",
HOSTNAMEDB.NAME LIKE "serverC*", "Customer C",
HOSTNAMEDB.NAME LIKE "serverD*", "Customer D",
) AS Customer,
...
FROM
... etc
What is the best way to work around this? Or am I reaching the limits of MS Access?

Related

How to prevent deletion or addition of records in an access database so that records can be modified but not removed or have additional ones added?

I'm creating an access database to keep track of the status of data closeout for the year 2021, from the 50 US states. I've made the states (Alabama through Wyoming) the primary key. I've also created forms for the corresponding tables for easy access, because I want to be able to look at states data from a form without having to look through a table, which is messier and more prone to error.
My question is: is it possible to set up the database (for both the tables and forms) so that no additional records can be added (I just want the 50 states), but also none can be deleted? I want to be able to enter and update the records themselves, but I don't want any of the state records to disappear, be renamed, or have additional records be added.
You can also use MsAccess Data-Driven Macros; in Datasheet view, use the Table group, and Click on 'BeforeChange', and add steps to the macro:
This example prevents 'inserts'.
Not rock-solid, of course; the user can delete the macro, and proceeds to insert.
Microsoft Doco for MsAccess Data Driven Macros
The Data Macro from the first answer will prevent deletion.
A ValidationRule including the 50 states will prevent adding records and changing the state names.
State field must also have these properties:
Required=Yes
AllowZeroLength=No
Indexed with "Yes (No Duplicates)".
ValidationRule for State field see below
In ("Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Idaho", "Hawaii", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming")
As others have noted you can use data macros on the table to prevent deletion of records, insertion of new records, or changes to specific fields. You may also want to consider simply hiding the table by right clicking it in the navigation pane, selecting properties, then checking the 'Hidden' textbox. You might also consider taking the 'lookup' tables like this and placing them in a separate 'lookup' database, linking to these tables from your current database, and then setting the 'read only' flag on the lookup database .accdb file to true. You will still be able to read the linked tables from your current database but you won't be able to change them.

Extract comma-separated values from JSON Records within a List with PowerQuery

As part of a tool I am creating for my team I am connecting to an internal web service via PowerQuery.
The web service returns nested JSON, and I have trouble parsing the JSON data to the format I am looking for. Specifically, I have a problem with extracting the content of records in a column to a comma separated list.
The data
As you can see, the data contains details related to a specific "race" (race_id). What I want to focus on is the information in the driver_codes which is a List of Records. The amount of records varies from 0 to 4 and each record is structured as id: 50000 (50000 could be any 5 digit number). So it could be:
id: 10000
id: 20000
id: 30000
As requested, an example snippet of the raw JSON:
<race>
<race_id>ABC123445</race_id>
<begin_time>2018-03-23T00:00:00Z</begin_time>
<vehicle_id>gokart_11</vehicle_id>
<driver_code>
<id>90200</id>
</driver_code>
<driver_code>
<id>90500</id>
</driver_code>
</race>
I want it to be structured as:
10000,20000,30000
The problem
When I choose "Extract values" on the column with the list, then I get the following message:
Expression.Error: We cannot convert a value of type Record to type
Text.
If I instead choose "Expand to new rows", then duplicate rows are created for each unique driver code. I now have several rows per unique race_id, but what I wanted was one row per unique race_id and a concatenated list of driver codes.
What I have tried
I have tried grouping the data by the race_id, but the operations allowed when grouping data do not include concatenating rows.
I have also tried unpivoting the column, but that leaves me with the same problem: I still get multiple rows.
I have googled (and Stack Overflowed) this issue extensively without luck. It might be that I am using the wrong keywords, however, so I apologize if a duplicate exists.
UPDATE: What I have tried based on the answers so far
I tried Alexis Olson's excellent and very detailed method, but I end up with the following error:
Expression.Error: We cannot convert the value "id" to type Number. Details:
Value=id
Type=Type
The error comes from using either of these lines of M code (one with a List.Transform and one without):
= Table.Group(#"Renamed Columns", {"race_id", "begin_time", "vehicle_id"},
{{"DriverCodes", each Text.Combine([driver_code][id], ","), type text}})
= Table.Group(#"Renamed Columns", {"race_id", "begin_time", "vehicle_id"},
{{"DriverCodes", each Text.Combine(List.Transform([driver_code][id], each Number.ToText(_)), ","), type text}})
NB: if I do not write [driver_code][id] but only [id] then I get another error saying that column [id] does not exist.
Here's the JSON equivalent to the XML example you gave:
{"race": {
"race_id": "ABC123445",
"begin_time": "2018-03-23T00:00:00Z",
"vehicle_id": "gokart_11",
"driver_code": [
{ "id": "90200" },
{ "id": "90500" }
]}}
If you load this into the query editor, convert it to a table, and expand out the Value record, you'll have a table that looks like this:
At this point, choose Expand to New Rows, and then expand the id column so that your table looks like this:
At this point, you can apply the trick #mccard suggested. Group by the first columns and aggregate over the last using, say, max.
This last step produces M code like this:
= Table.Group(#"Expanded driver_code1",
{"Name", "race_id", "begin_time", "vehicle_id"},
{{"id", each List.Max([id]), type text}})
Instead of this, you want to replace List.Max with Text.Combine as follows:
= Table.Group(#"Changed Type",
{"Name", "race_id", "begin_time", "vehicle_id"},
{{"id", each Text.Combine([id], ","), type text}})
Note that if your id column is not in the text format, then this will throw an error. To fix this, insert a step before you group rows using Transform Tab > Data Type: Text to convert the type. Another options is to use List.Transform inside your Text.Combine like this:
Text.Combine(List.Transform([id], each Number.ToText(_)), ",")
Either way, you should end up with this:
An approach would be to use the Advanced Editor and change the operation done when grouping the data directly there in the code.
First, create the grouping using one of the operations available in the menu. For instance, create a column"Sum" using the Sum operation. It will give an error, but we should get the starting code to work on.
Then, open the Advanced Editor and find the code corresponding to the operation. It should be something like:
{{"Sum", each List.Sum([driver_codes]), type text}}
Change it to:
{{"driver_codes", each Text.Combine([driver_codes], ","), type text}}

Access Query - Syntax error

I have created a database with the intention of allowing analysis of patients blood test results for a certain condition. The query itself is working fine however is unsearchable (in other queries i've generated I've identified this is was because I had spaces in the headings and so removed these)
This query is now duplicating patients for each positive test they have from the selection. This seems to be linked to the .value column as goes away when this is removed however then the query becomes unsearchable using the quick search tool.
Is there any solution to this? I'm using the query wizard to build these. Believe the problem is with the 'OtherImmunology.Value' part
SELECT cci.rq6number,
pi.firstname,
pi.lastname,
pi.nhsnumber,
pi.dob,
Datediff("yyyy", [dob], [initialdiagnosisdate]) AS AgeAtDiagnosis,
pi.gender,
pi.[diagnosis(iapconsensuscriteria)],
cci.initialdiagnosisdate,
cci.steroidtherapy,
cci.responsetosteroids,
cci.igg4level,
cci.[igg4actualresult(mg/dl)],
cci.serumigg,
cci.[serumigg result(g/l)],
cci.otherimmunologytested,
cci.otherimmunology,
cci.** otherimmunology.VALUE,
cci **.[ca19-9level],
cci.[ca19-9actualresult(ku/l)],
cci.surgery,
cci.otherautoimmuneconditions,
cci.autoimmunecondition,
cci.completed
FROM [patient information] As pi
INNER JOIN [Clinical Contact Informtion] As cci
ON pi.[rq6number] = cci.[rq6number];

Access - Searching for a value

I am trying to display a word in a field if another field displays something.
Say I have two fields called [Fruit] and [Description]
in [Fruit] would be
RApple
GApple
if [Fruit] states "RApple" I want the [Description] to read "Red Apple" - also would the [Description] save back to the table?
I have tried IIf and I can't get that to work.
I have the same thing working in Excel using ISNUMBER and SEARCH
=IF(ISNUMBER(SEARCH("RApple",B1)),"Red Apple",IF(ISNUMBER(SEARCH("GApple",B1)),"Green Apple")
Can something like this work in Access?
Well, if we were simply testing 2 strings and they were always in that format you provided, it could be as simple as :
IIf([color] = "RApple", "Red Apple", IIf([color] = "GApple", "Green Apple", "No Match"))
To search for the color :
IIf(Left([Fruit],1)="R","Red",IIf(Left([Fruit],1)="G","Green","No Match"))
This would all be better off in VBA, however given the context of your question, it doesn't sound like it's in scope, since this seems like a simple test.
I also agree with #HansUp in stating that this is a bad design with your data. When you can, you want to avoid prying logic out of strings. It would be much better with two fields: [Color] and [Fruit]. From there, you could make the string you so desire if you needed to (RApple, etc.)

MS Access - Max function with Date not working

Okay, so I built a database that allows me to keep track of calls being made to potential customers. Basically, the user generates a call list, and after calling each customer, they update the Call Status field in one of my tables to either "Person Reached", "Line Busy", "Disconnected Number", etc.
The problem I am having is that when I run the "Generate Call List" query (which I use to populate the Call List table), I am getting people who have already been reached. I have a condition that excludes anyone with a Call Status of "Person Reached", but for some reason it's not working. Here's the SQL.
SELECT [Telephone Status].Patient_ID, Max([Telephone Status].Date_Called)
AS [Date Last Called]
FROM [Telephone Status]
WHERE ((([Telephone Status].Call_Status_Details)="Call Back Later") AND
(([Telephone Status].Call_Status)<>"Person Reached"))
GROUP BY [Telephone Status].Patient_ID;
I thought that by using the Max function with the Date_Called field, that I would be excluding individuals who have a "Person Reached" status from the most recent call (Max), but I am still getting people who have been reached.
How can I check for this condition ("Person Reached") for the most recent Date_Called entry for each participant, and exclude them if the condition is True (Person was reached)?
The problem I am having is that when I run the "Generate Call List" query (which I use to populate the Call List table), I am getting people who have already been reached.
And how do you know that statement to be true? I think you need to examine the data in the [Telephone Status] table ... the Date_Called, Call_Status_Details, and Call_Status fields for one of the Patient_ID which was erroneously included on the call list.
I have a condition that excludes anyone with a Call Status of "Person Reached", but for some reason it's not working.
Not exactly ...
SELECT
ts.Patient_ID,
Max(ts.Date_Called) AS [Date Last Called]
FROM [Telephone Status] AS ts
WHERE
ts.Call_Status_Details = "Call Back Later"
AND ts.Call_Status <> "Person Reached"
GROUP BY ts.Patient_ID;
... so you have two criteria which both must be True.
Some ways a "person reached" could be included in the call list query are:
Call_Status_Details = "Call Back Later" but Call_Status is anything
other than "Person Reached", such as "Person R eached"; Person
Reachd"; etc.
A record with Call_Status_Details = "Call Back Later", a more recent
Date_Called than the last Call_Status = "Person Reached", but
some other valid value for Call_Status.
Indexes for those fields are corrupt.
The first is a data quality issue. You need to verify the data is consistently stored as you and your query expect.
I don't know about the second possibility. It depends on your business rules and how they are implemented.
The last possibility, index corruption, appears to be rare in my experience, but I've heard it can happen. Compact & Repair could fix it. See Tony Towes' Corrupt Microsoft Access MDBs FAQ for more detailed information.
Edit: You have a "Generate Call List" query which populates a Call List table. That is a situation where the Call List table could get out of sync with the latest updates to the [Telephone Status] table. It would be better to use the query itself for the call list rather than duplicating (possibly outdated) information in a separate table.