MS Access Query using IFF to compare values - ms-access

I am trying to build a query which will look at the data in two fields in two different tables and check to see if the data is the same, if it is I want it to return the number of times it is matched, if it isn't I simply want it to return the text saying "No viewings".
I have constructed this query in my access database which has the field from the first table "Property" and the second field I want it to compare the data with, "Viewings". I have build the following expression using the build tool, however I am stuck to make it work since every time I get this error message when trying to run the query: "Your query does not include the specified expression 'Property Viewed' as part of an aggregate function."
totalViewings: IIf([Viewings]![Property Viewed]=[Property]![ID],Count([Viewings]![Property Viewed]=[Property]![ID]),"No Viewings")
Any help how to overcome this error would be very appreciated.
Thanks

I would suggest doing something like this:
1) Assuming this is something you are developing yourself, make sure your data structure is all in order first. Since I dislike relatively code-hostile identifiers, I'd have the tables as so -
Properties - PropertyID (AutoNumber, primary key), HouseNumberOrName, Street, etc.
Viewings - ViewingID (AutoNumber, primary key), PropertyID (Number/Long Integer), ViewingDate, etc.
In the Relationships view, Properties.PropertyID would then be set up to point to Viewings.PropertyID in a one-to-many relation.
2) Your actual query I would then break into two, the first to compile the data and the second to format it for display. The first would go like this, saved as ViewingCounts...
SELECT Properties.PropertyID, Count(Viewings.PropertyID) As ViewingCount
FROM Properties LEFT JOIN Viewings ON Properties.PropertyID = Viewings.PropertyID
GROUP BY Properties.PropertyID;
... and the second like this, saved as ViewingCountsForDisplay:
SELECT Properties.*, IIf(ViewingCount = 0, 'No viewings', ViewingCount) AS Viewings
FROM Properties INNER JOIN ViewingCounts ON Properties.PropertyID = ViewingCounts.PropertyID
ORDER BY Properties.PropertyID;

Related

Transforming Results from Rows into Columns

I have a data set that contains both common and unique values, which I am attempting to return in a useable format to allow further analyse/work to be taken based on said results.
The desired result would be to have a script that would recognise the common values such as mpan/serial_number/read_at so as to only return a single row, but also to recognise the unique values those being the read_at and identifier.
Currently my script returns a unique row based on the identifier and the value, but I would like to be able to return a unique row for the read_at date for as many identifiers and values as are held. In most cases there are only two identifiers and values, but there could be as many as five.
The issue I have is that when I try to make distinct work, it will only then return the first found result, where I am expecting a pair of results at minimum. I am also unclear as to how I could stop getting a new row and instead create the result as an additional column?
My base script which pulls everything is as below, I have tried a few variances on this, but think this would likely be the best place to start from with regards to any help you may be able to offer?
SELECT *
FROM consumer.stg_d0010_v2_026_027
/*LEFT JOIN consumer.stg_d0010_v2_026_028_029
ON consumer.stg_d0010_v2_026_028_029.file_identifier = consumer.stg_d0010_v2_026_027.file_identifier
AND consumer.stg_d0010_v2_026_028_029.mpan = consumer.stg_d0010_v2_026_027.mpan*/
LEFT JOIN consumer.stg_d0010_v2_026_028_030_032
ON consumer.stg_d0010_v2_026_028_030_032.file_identifier = consumer.stg_d0010_v2_026_027.file_identifier
AND consumer.stg_d0010_v2_026_028_030_032.mpan = consumer.stg_d0010_v2_026_027.mpan
LEFT JOIN consumer.stg_d0010_v2_026_028_030_033
ON consumer.stg_d0010_v2_026_028_030_033.file_identifier = consumer.stg_d0010_v2_026_027.file_identifier
AND consumer.stg_d0010_v2_026_028_030_033.mpan = consumer.stg_d0010_v2_026_027.mpan
where consumer.stg_d0010_v2_026_028_030_032.read_At > '2022-10-01'
and consumer.stg_d0010_v2_026_027.mpan in (
)
Example dataset in image below.
enter image description here
And desired outcome
enter image description here
The issue I have is that when I try to make distinct work, it will only then return the first found result, where I am expecting a pair of results at minimum. I am also unclear as to how I could stop getting a new row and instead create the result as an additional column?

How to make a table on Access using "Count" and Age Range?

I downloaded a record of all the people on the first fleet from this website. http://firstfleet.uow.edu.au/download.html
I downloaded the Excel and imported it into Access. In the document, certain people’s age is not known so they are simply put as -1.
I am trying to make this table but I am struggling.
I’ve tried doing it by creating a table but that was too hard so I decided to create a query instead. I am using “Crosstab” but failing to use it successfully.
When I do try to sub the -1 for unknown:
Messages like this pop up:
How do we add the table in but sub the -1 for unknown while keeping the layout the same? I am hard stuck at a place where I cannot even view how my query looks.
How do I even make the layout the same as the picture shown above?
UPDATE:
Calculate the age groups with Switch() function and use that calculated field for CROSSTAB RowColumn. I renamed the Age field in table from the original import name to shorten the expression.
TRANSFORM Count(Convicts.ID) AS CountOfID
SELECT Switch([Age]=-1,"Unknown",[Age]<15,"10-14",[Age]<20,"15-19",[Age]<25,"20-24",[Age]<30,"25-29",[Age]<35,"30-34",[Age]<40,"35-39",[Age]<45,"40-44",[Age]<50,"45-49",[Age]<60,"50-59",[Age]<100,"60-99") AS AgeGrp
FROM Convicts
GROUP BY Switch([Age]=-1,"Unknown",[Age]<15,"10-14",[Age]<20,"15-19",[Age]<25,"20-24",[Age]<30,"25-29",[Age]<35,"30-34",[Age]<40,"35-39",[Age]<45,"40-44",[Age]<50,"45-49",[Age]<60,"50-59",[Age]<100,"60-99")
PIVOT Convicts.Gender;
The total row is added by clicking the Sigma(Totals) icon on the ribbon when query is in Datasheet view.
A simpler calculation will generate more groups:
TRANSFORM Count(Convicts.ID) AS CountOfID
SELECT Partition([Age],0,100,5) AS AgeGrp
FROM Convicts
GROUP BY Partition([Age],0,100,5)
PIVOT Convicts.Gender;
But a little adjustment to the SELECT clause will get same output as the first:
SELECT IIf([Age]=-1,"Unknown",IIf([Age]<50,Partition([Age],0,50,5),IIf([Age]<60,"50:59","60:99"))) AS AgeGrp
Could add a field in table and use one of those expressions in UPDATE action SQL to add calculated AgeGrp, which would simplify the CROSSTAB and other queries needing that group identifier.

Testing if a row exists in a table for a report

I'm trying to write a report that lists all the rows from a master table and inserts a field ("Y"/"N") if the key exists in a current-use table. For example, the COLOR_MASTER table has 256 colors by COLOR_NAME (field/key). The CURRENT_PROJECTS has a row for each project and the COLOR_NAME (field). I want to list all the COLOR_MASTER rows and then on the same print line a "Y" or "N" if that COLOR_NAME is used in the CURRENT_PROJECTS table.
I've tried to mess around with it in the Design View and have had no luck. The JOIN that was created looks basically like this and how I want the report is following the dashes:
RIGHT JOIN COLOR_MASTER ON CURRENT_PROJECTS.COLOR_NAME =
COLOR_MASTER.COLOR_NAME ON CURRENT_PROJECTS.COLOR_NAME =
COLOR_MASTER.COLOR_NAME;
--------
Color Used
BLUE
RED Y
YELLOW
I have no expertise in JOINs and I don't understand why this JOIN was created or what I need to do to fix it. Based on my reading, I guess it's trying to do an outer join.
Currently, I'm just trying to show the COLOR_NAME if used as I don't know how to test that it is used and convert it to "Y". I don't care if the color is used once or twenty times and I don't really want any data from the CURRENT_PROJECTS table.
Under the "Used" column I now have "#Error" on all lines. So, I'm figuring that the RIGHT JOIN has an error.
Any guidance is appreciated.
Thanks
I expect the RIGHT JOIN is defined in the table Relationships builder and a query using the tables adopts the established link. If you want to change the join type in a query then with query in design view, double click on the line linking tables to open the Join Properties dialog.
If there is only one record per project in Current_Projects and a color can be used only once, simply:
SELECT Color_Master.Color_Name, IIf([Current_Projects].[Color_Name] Is Null,"N","Y") AS Used
FROM Color_Master LEFT JOIN Current_Projects ON Color_Master.Color_Name = Current_Projects.Color_Name;
However, it sounds like each color can be used for multiple projects. So will need to use GROUP BY or DISTINCT query joined to the Master_Colors table:
SELECT DISTINCT Current_Projects.Color_Name FROM Current_Projects;
SELECT Color_Master.Color_Name, IIf([Query1].[Color_Name] Is Null,"N","Y") AS Used
FROM Query1 RIGHT JOIN Color_Master ON Query1.Color_Name = Color_Master.Color_Name;
Here is all-in-one SQL:
SELECT Color_Master.Color_Name, IIf([Query1].[Color_Name] Is Null,"N","Y") AS Used
FROM (SELECT DISTINCT Current_Projects.Color_Name FROM Current_Projects) AS Query1
RIGHT JOIN Color_Master ON Query1.Color_Name = Color_Master.Color_Name;
If you don't want anything displayed for the N result then use Null without quote marks in the expression.
An alternative is DLookup() but domain aggregate functions can perform slowly in query or textbox expression.
Advise not to save the calculated value to table, just calculate when needed.
You don't have to do it all in one query. Start by building a query that as the IDs of all the colors currently in use. Name it something like ColorsInUse and save it.
It could be something as simple as:
SELECT [COLOR_NAME] FROM [CURRENT_PROJECTS] GROUP BY [COLOR_NAME]
Then all you have to do is run the following queries:
UPDATE [COLOR_MASTER] SET [MyField]="N"
UPDATE [COLOR_MASTER] SET [MyField]="Y" WHERE [COLOR_NAME] IN [ColorsInUse]
Another way of doing it is by using DLookup. Something like this:
UPDATE [COLOR_MASTER] SET [MyField]=IIF(NZ(DLookup("[COLOR_NAME]","[CURRENT_PROJECTS]","[COLOR_NAME]='" & [COLOR_NAME] & "'"),"")="","N","Y")
Some notes: You should not use a text field (like a name) as your key. You should always use numerical IDs. You should also never use a text Y/N. Use an actual Yes/No field instead.

Searching ALL ROWS in a Group using IIF Expression

I am working on a report that displays patient names (as groups with drilldowns) and several fields related to their visits. I have created a column in the report to display whether or not a specific value appears in the 'LocationID' column. The expression I used is
=IIF(Fields!LocationID.Value="WELL","Y","N")
I thought this was working great, it displays Y or N next to each name to let me know if 'WELL' was in their 'LocationID'. I checked several to ensure that this was going to work and discovered that there was a LocationID code of 'WHS' and since I have the rows ordered by Name and LocationID if there was a WHS visit it shows up at the top of the group and my expression is only seeing this top item. How can this expression be written differently so that it searches the entire result of each group? Depending on the date range a patient may have one visit or they may have ten. I need to check all visits that are returned. Perhaps there is a better method. Thanks in advance.
I agree with jimmy8ball that the easiest way to solve most issues like this is to push some logic back into the SQL layer.
However, if you really want to do this via SSRS functionality, then you could implement a substring search against a lookupset. Assuming you have a patient id in your dataset that is unique for each patient (I hope your group isn't on the name) then...
=Iif(InStr(Join(Lookupset(Fields!patientid.Value, Fields!patientid.Value, Fields!LocationsID.Value, "dataset"), ","), "WELL") > 0, "Y", "N")
Which says, "Search through the dataset for all rows related to my patientid, join every location into a comma deliminated string, search the string for the text "WELL" and return "Y" if it's found.
Obviously if you have locations in your dataset like "WELLY", these will become false positives and you'll have to implement some more nested logic. Try appending a value (perhaps !) to the lookupset return field so that you can search for "WELL!" or some other terminator character.

Mysql select part of field and return full value

Good day all,
I have a field called mCodes which has the exact length (7) throughout the table but with different values i.e. a few records with 5036100, 5036102, 5036103, 7010100, 7010101 etc.
I am using a select statement to first search for the first 4 characters i.e 5036 which will return all the records with 5036 just fine
I now need to return the actual full value of the records 5036100 etc. without recreating another sql statement. My statement I am using is as follow -
SELECT LEFT(MCODE, 4), MAKE, MODEL, NEWPRICE23 FROM mautogd1015 WHERE LEFT(MCODE, 4) = '5036'
I have racked my brain over this for a few hours now, any help will be appreciated.
Try something like this.
SELECT MCODE, MAKE, MODEL, NEWPRICE23 FROM mautogd1015 WHERE LEFT(MCODE, 4) = '5036'