Finding number of occurrences for specific value - sql

I'm trying to create a field (calculation result) in FileMaker Pro 13 that will return the number of times a specific value is selected in a specific field.
For Example:
Say you have Table 1. Table 1 only has 1 field named Field 1. Field 1 is a drop down list field with the options "A","B", & "C". The following data is from the records of Table 1 using the field, Field 1:
Record 1: Table 1::Field 1 = "A"
Record 2: Table 1::Field 1 = "A"
Record 3: Table 1::Field 1 = "B"
Record 4: Table 1::Field 1 = "C"
What I want is a counter that searches across the records for table one and finds how many times a certain option is selected. For example, I want to know how many times "A" was selected in Field 1 and it would return "2".
What I have tried to do so far is the following but it hasn't worked out so hot (returns "?"):
ExecuteSQL(
"SELECT Field 1
FROM Table 1
WHERE Field 1 = 'A'"
;"";"")
Any suggestions for a correct SQL script?

The correct version of your Execute
ExecuteSQL(
"SELECT Count(\"Field 1\")
FROM \"Table 1\"
WHERE \"Field 1\" = ?"
;"";"";"A")
When you use ExecuteSQL, you're passing a string into FileMaker's function and then behind the scenes FileMaker uses that string and the various other pieces you give it to perform the action.
If you have a space in your field or table name, e.g. Field 1, FileMaker thinks you mean "Select a field name Field and a field named 1. You need to quote the field name if it contains spaces or special characters, but you can't use just regular double quotes because that would end the string.
The way to fix it is what I did above; escape the double quotes around the field or table name.
Also, the ? and the "A" at the bottom allows you to pass data into the query, i.e. parameterizing the query. This means you could do a loop where each iteration of the loop you pass in a different value where I have "A". E.g. You could do this:
ExecuteSQL(
"SELECT Count(\"Field 1\")
FROM \"Table 1\"
WHERE \"Field 1\" = ?"
;"";""; Table 1::Search Field)
or
ExecuteSQL(
"SELECT Count(\"Field 1\")
FROM \"Table 1\"
WHERE \"Field 1\" = ?"
;"";"";$searchValue)
Be careful though, ExecuteSQL doesn't cache records that it pulls if you're in a server/client environment so this calculation could get pretty sluggish if you have a lot of records in the table, you're going over the wan, or both. I would suggest trying to get the count a different way.

Select count(*) from Table1 where Field1='A'

Related

Access 10 sql query

I want to use LIKE operator in access 10 sql query with variable.
Example:
temporary variable var contains value bs
var = "bs"
I want to match every String that starts with value of temporary variable followed by zero or more numbers.
I am trying to fire the query:
select * from xyz where variety LIKE "#[tempvars]![var] + [0-9]*"
It is returning 0 records.
Thankz for the help.
You need to refer to your tempvar outside of the quotes, and use & for concatenation:
select * from xyz where variety LIKE "#" & [tempvars]![var] & "[0-9]*"
This will return all records where variety starts with a literal #, then whatever is in [tempvars]![var], then a number, and then any amount of characters.
You can check if that variety is available in your table or not. If that variety is available in your table then don't search with like operator and otherwise use like operator.

PowerQuery - Using a cell in a table as part of the code in a query (dynamically or not)

I am trying to use a cell as a parameter in Excel powerquery. The query works without this, but I have to manually input the values, which I need to constantly change them in the query in other to get the results that I want.
Query (Advanced Editor):
let
Criteria01 = Excel.CurrentWorkbook(){[Name="Servers"]}[Content][ServerSearch]{0},
Criteria02 = Excel.CurrentWorkbook(){[Name="Servers"]}[Content][ServerSearch]{1},
Criteria03 = Excel.CurrentWorkbook(){[Name="Servers"]}[Content][ServerSearch]{2},
Source = Sql.Database("SERVERNAMEHERE", "DATABASENAMEHERE", [Query="SELECT DISTINCT [...........] AND (TABLEPREF.COLUMNHERE like '%MANUALVALUE01%' OR#(lf)TABLEPREF.COLUMNHERE like '%MANUALVALUE02%' OR#(lf)TABLEPREF.COLUMNHERE like '%MANUALVALUE03%' OR#(lf)TABLEPREF.COLUMNHERE like Criteria01)#(lf)#(lf)#(lf)order by 1 asc"])
in
Source
"Servers" is the table name and "ServerSearch" is the column header. If I check the step for Criteria01/etc it will show me the correct value of that table that I need to use.
Original query done in Sql-Server. I have no problems when running the query with only LIKE '%MANUALVALUES%' lines.
My main goal is to automatically get N values of "MANUALVALUES" from a table in a sheet, which will be used as an input for comparing WHERE TABLEPREF.COLUMNHERE like '%VALUEHERE%'. I must use this and I can't get the whole table/database because there are way too many results besides the ones that I want.
However for test purposes at this moment, I am trying to use only 1-3 values, the first 3 of this table (Criteria{0}{1}{2} in the query above). However, if I try to do something like TABLEPREF.COLUMNHERE like Criteria01 I get the following error:
DataSource.Error: Microsoft SQL: Invalid column name 'Criteria01'.
Details:
DataSourceKind=SQL
DataSourcePath=dalsql390;itdw
Message=Invalid column name 'Criteria01'.
Number=207
Class=16
So my questions are:
I am getting the table cell value by the right way? Meaning:
Excel.CurrentWorkbook(){[Name="Servers"]}[Content][ServerSearch]{0}.
How do I refer this value in my query? Since the way that I wrote
that query bought me that error.
Also please note that if change TABLEPREF.COLUMNHERE like
Criteria01 to CHG1.CI_Name like "Criteria01" I get the
following error:
Expression.SyntaxError: Token Comma expected.
After fixed 1 and 2, how can I use this dynamically? For
example, instead of getting values of index 1 2 3, what if I want to
use a whole table? I know that using
Excel.CurrentWorkbook(){[Name="Servers"]}[Content] will bring me the whole table of values (1 column, unknown number of rows), but
how do I use this table content 1 by 1 in my query?
That will get the value, but you can't refer to steps inside of text values by putting the step name inside of it.
You have a couple options for doing this dynamically.
Use Value.NativeQuery to create a parameterized query where you can pass in other values as parameters. For example, Value.NativeQuery(Sql.Database("SERVERNAMEHERE", "DATABASENAMEHERE"), "select #a, #b", [a = 1, b = "x"]) will return the table [1, x]. You can put in the step name in the record value to pass that it (e.g. replace "x" with Criteria01).
Add the text values directly in the query field, e.g. [Query = "select " & Criteria01 ";"]. This is highly discouraged since this can lead to SQL injection issues.
For the third question, it depends what you want to do with the list of values. At some point you will likely need List.Accumulate to turn them all into a single text value which can be placed in the query value, and maybe to turn them into a record to place into the parameters value.

how to use sql to Check if a certain column value contains another certain column value

I have a table, with 2 specific columns "log_number" and "message"
The "message" text value should contain the "log_number" value
Now I want to write a sql select to check if there is any bad rows which break the rules ! how can I do it ...
If I understand your question... this will list the records for which the log_number string is not contained in your message string:
SELECT *
FROM your_table
WHERE instr(message, log_number) < 1;

Problem with MySQL Select query with "IN" condition

I found a weird problem with MySQL select statement having "IN" in where clause:
I am trying this query:
SELECT ads.*
FROM advertisement_urls ads
WHERE ad_pool_id = 5
AND status = 1
AND ads.id = 23
AND 3 NOT IN (hide_from_publishers)
ORDER BY rank desc
In above SQL hide_from_publishers is a column of advertisement_urls table, with values as comma separated integers, e.g. 4,2 or 2,7,3 etc.
As a result, if hide_from_publishers contains same above two values, it should return only record for "4,2" but it returns both records
Now, if I change the value of hide_for_columns for second set to 3,2,7 and run the query again, it will return single record which is correct output.
Instead of hide_from_publishers if I use direct values there, i.e. (2,7,3) it does recognize and returns single record.
Any thoughts about this strange problem or am I doing something wrong?
There is a difference between the tuple (1, 2, 3) and the string "1, 2, 3". The former is three values, the latter is a single string value that just happens to look like three values to human eyes. As far as the DBMS is concerned, it's still a single value.
If you want more than one value associated with a record, you shouldn't be storing it as a comma-separated value within a single field, you should store it in another table and join it. That way the data remains structured and you can use it as part of a query.
You need to treat the comma-delimited hide_from_publishers column as a string. You can use the LOCATE function to determine if your value exists in the string.
Note that I've added leading and trailing commas to both strings so that a search for "3" doesn't accidentally match "13".
select ads.*
from advertisement_urls ads
where ad_pool_id = 5
and status = 1
and ads.id = 23
and locate(',3,', ','+hide_from_publishers+',') = 0
order by rank desc
You need to split the string of values into separate values. See this SO question...
Can Mysql Split a column?
As well as the supplied example...
http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/
Here is another SO question:
MySQL query finding values in a comma separated string
And the suggested solution:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set

How to Replace Multiple Characters in Access SQL?

I'm a novice at SQL, so hopefully someone can spell this out for me. I tried following the "Replace Multiple Strings in SQL Query" posting, but I got stuck.
I'm trying to do the same thing as the originator of the above posting but with a different table and different fields. Let's say that the following field "ShiptoPlant" in table "BTST" has three records (my table actually has thousands of records)...
Table Name: BTST
---------------
| ShiptoPlant |
| ----------- |
| Plant #1 |
| Plant - 2 |
| Plant/3 |
---------------
Here's what I'm trying to type in the SQL screen:
SELECT CASE WHEN ShipToPlant IN ("#", "-", "/") Then ""
ELSE ShipToPlant END FROM BTST;
I keep getting the message (Error 3075)...
"Syntax error (missing operator) in query expression
'CASE WHEN ShiptoPlant IN (";","/"," ") Then "" ELSE ShipToPlant END'."
I want to do this operation for every character on the keyboard, with exception of "*" since it is a wildcard.
Any help you could provide would be greatly appreciated!
EDIT: Background Information added from the comments
I have collected line-item invoice-level data from each our 14 suppliers for the 2008 calendar year. I am trying to normalize the plant names that are given to us by our suppliers.
Each supplier can call a plant by a different name e.g.
Signode Service on our master list could be called by suppliers
Signode Service
Signode - Service.
SignodeSvc
SignodeService
I'm trying to strip non-alphanumeric chars so that I can try to identify the plant using our master listing by creating a series of links that look at the first 10 char, if no match, 8 char, 6, 4...
My basic hang-up is that I don't know how to strip the alphanumeric characters from the table. I'll be doing this operation on several columns, but I planned on creating separate queries to edit the other columns.
Perhaps I need to do a mass update query that strips all the alphanumerics. I'm still unclear on how to write it. Here's what I started out with to take out all the spaces. It worked great, but failed when I tried to nest the replace
UPDATE BTST SET ShipToPlant = replace(ShipToPlant," ","");
EDIT 2: Further Information taken from Comments
Every month, up to 100 new permutations of our plant names appear in our line item invoice data- this could represent thousands of invoice records. I'm trying to construct a quick and dirty way to assign a master_id of the definitive name to each plant name permutation. The best way I can see to do so is to look at the plant, address, city and state fields, but the problem with this is that these fields have various permutations as well, for example,
128 Brookview Drive
128 Brookview Lane
By taking out alphanumerics and doing
LEFT(PlantName,#chars) & _
LEFT(Address,#chars) & _
LEFT(City,#chars) & _
LEFT(State,#chars)
and by changing the number of characters until a match is found between the invoice data and the Master Plant Listing (both tables contain the Plant, Address, City and State fields), you can eventually find a match. Of course, when you start dwindling down the number of characters you are LEFTing, the accuracy becomes compromised. I've done this in excel and had decent yield. Can anyone recommend a better solution?
You may wish to consider a User Defined Function (UDF)
SELECT ShiptoPlant, CleanString([ShiptoPlant]) AS Clean
FROM Table
Function CleanString(strText)
Dim objRegEx As Object
Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.IgnoreCase = True
objRegEx.Global = True
objRegEx.Pattern = "[^a-z0-9]"
CleanString = objRegEx.Replace(strText, "")
End Function
You could use the built in Replace function within Access
SELECT
Replace(Replace(Replace(ShipToPlant, "#", ""), "-", ""), "/", "") AS ShipToPlant
FROM
BTST
As others have said, within Access you can write your own functions in VBA and use them in your queries.
EDIT:
Here's a way to handle the nested Replace limit by wrappering the Replace function within our own function. It feels dirty but it works- put this in a module within Access
Public Function SuperReplace(ByRef field As String, ByVal ReplaceString As String) As String
' Size this as big as you need... it is zero-based by default'
Dim ReplaceArray(3) As String
'Fill each element with the character you need to replace'
ReplaceArray(0) = "#"
ReplaceArray(1) = "-"
ReplaceArray(2) = "/"
ReplaceArray(3) = " "
Dim i As Integer
For i = LBound(ReplaceArray) To UBound(ReplaceArray)
field = Replace(field, ReplaceArray(i), ReplaceString)
Next i
SuperReplace = field
End Function
Then test it with this query
SELECT
SuperReplace(ShipToPlant,"") AS ShipToPlant
FROM
BTST
You might want to take this an expand it so that you can pass in an array of strings instead of hard-coding them into the function.
EDIT 2:
In response to the additional information in the comments on the question, here's a suggestion for how you might want to handle the situation differently. The advantage to this apprach is that once you have mapped in a plant name permutation, you won't need to perform a string replace on future data in future years, only add new plant names and permutations to the map.
Start with creating another table, let's call it plant_map
CREATE TABLE plant_map (id AUTOINCREMENT PRIMARY KEY, name TEXT, master_id LONG)
into plant_map, add all of the permutations for plant names and insert the id for the name you wish to use to refer to a particular plant name permutation group with, into the master_id field. From your comments, I'll use Signode Service
INSERT INTO plant_map(name, master_id) VALUES ("Signode Service", 1);
INSERT INTO plant_map(name, master_id) VALUES ("Signode Svc", 1);
INSERT INTO plant_map(name, master_id) VALUES ("Signode - Service", 1);
INSERT INTO plant_map(name, master_id) VALUES ("Signode svc", 1);
INSERT INTO plant_map(name, master_id) VALUES ("SignodeService", 1);
Now when you query BTST table, you can get data for Signode Service using
SELECT
field1,
field2
FROM
BTST source
INNER JOIN
(
plant_map map1
INNER JOIN
plant_map map2
ON map1.master_id = map2.id
)
ON source.ShipToPlant = map1.name
WHERE
map2.name = "Signode Service"
Data within table BTST can remain unchanged.
Essentially, this is joining on the plant name in BTST to the name in plant_map then, using master_id, self joining on id within plant_map so that you need only pass in one "common" name. I would advise putting an index on each of the columns name and master_id in plant_map as both fields will be used in joins.
Don't think Access supports the CASE statement. Consider using iif:
iif ( condition, value_if_true, value_if_false )
For this case you can use the REPLACE function:
SELECT
REPLACE(REPLACE(REPLACE(yourfield, '#', ''), '-', ''), '/', '')
as FieldName
FROM
....
Create a public function in a Code module.
Public Function StripChars(ByVal pStringtoStrip As Variant, ByVal pCharsToKeep As String) As String
Dim sChar As String
Dim sTemp As String
Dim iCtr As Integer
sTemp = ""
For iCtr = 1 To Len(pStringtoStrip)
sChar = Mid(pStringtoStrip, iCtr, 1)
If InStr(pCharsToKeep, sChar) > 0 Then
sTemp = sTemp & sChar
End If
Next
StripChars = sTemp
End Function
Then in your query
SELECT
StripChars(ShipToPlant, "abcdefghijklmnopqrstuvwxyz0123456789") AS ShipToPlantDisplay
FROM
BTST
Notes - this will be slow for lots of records - if you what this to be permanent then create an update query using the same function.
EDIT: to do an Update:
UPDATE BTST
SET ShipToPlant = StripChars(ShipToPlant, "abcdefghijklmnopqrstuvwxyz0123456789")
OK, your question has changed, so the solution will too. Here are two ways to do it. The quick and dirty way will only partially solve your issue because it won't be able to account for the more odd permutations like missing spaces or misspelled words. The quick and dirty way:
Create a new table - let's call it
tChar.
Put a text field in it - the
char(s) you want to replace - we'll
call it char for this example
Put all the char or char combinatios that you want removed in this table.
Create and run the query below.
Note that it will only remove one
item at a time, but you can also put
different versions of the same
replacement in it too like ' -' or
'-'
For this example I created a table called tPlant with a field called ShipToPlant.
SELECT tPlant.ShipToPlant, Replace([ShipToPlant],
(SELECT top 1 char
FROM tChar
WHERE instr(ShipToPlant,char)<>0 ORDER BY len(char) Desc),""
) AS New
FROM tPlant;
The better (but much more complex) way. This explanation is going to be general because it would be next to impossible to put the whole thing in here. If you want to contact me directly use my user name at gmail.:
Create a table of Qualifiers -
mistakes that people enter like svc
instead of service. Here you would
enter every wierd permutation you
get.
Create a table with QualifierID and
Plant ID. Here you would say which
qualifier goes to which plant.
Create a query that joins the two
and your table with mistaken plant
names in it. Use instr so say what
is in the fields.
Create a second query that
aggragates the first. Count the
instr field and use it as a score.
The entry with the highest score is
the plant.
You will have to hand enter the ones
it can't find, but pretty soon that
will be next to none as you have
more and more entries in the table.
ughh
You have a couple different choices. In Access there is no CASE in sql, you need to use IIF. It's not quite as elegant as the solutions in the more robust db engines and needs to be nested for this instance, but it will get the job done for you.
SELECT
iif(instr(ShipToPlant,"#")<>0,"",
iif(instr(ShipToPlant,"-")<>0,"",
iif(instr(ShipToPlant,"/")<>0,"",ShipToPlant ))) AS FieldName
FROM BTST;
You could also do it using the sql to limit your data.
SELECT YourID, nz(aBTST.ShipToPlant,"") AS ShipToPlant
FROM BTST LEFT JOIN (
SELECT YourID, ShipToPlant
FROM BTST
WHERE ShipToPlant NOT IN("#", "-", "/")
) as aBTST ON BTST.YourID=aBTST.YourID
If you know VB you can also create your own functions and put them in the queries...but that is another post. :)
HTH
SELECT
IIF
(
Instr(1,ShipToPlant , "#") > 0
OR Instr(1,ShipToPlant , "/") > 0
OR Instr(1,ShipToPlant , "-") > 0, ""
, ShipToPlant
)
FROM BTST
All - I wound up nesting the REPLACE() function in two separate queries. Since there's upwards of 35 non-alphanumeric characters that I needed to replace and Access limits the complexity of the query to somewhere around 20 nested functions, I merely split it into two processes. Somewhat clunky, but it worked. Should have followed the KISS principle in this case. Thanks for your help!
I know this is a really old question, but I stumbled over it whilst looking for a solution to this problem, but ended up using a different approach.
The field that I wish to update is called 'Customers'. There are 20-odd accented characters in the 'CustName' field for which I wish to remove the diacritics - so (for example) ã > a.
For each of these characters I created a new table 'recodes' with 2 fields 'char' and 'recode'. 'char' contains the character I wish to remove, and 'recode' houses the replacement.
Then for the replace I did a full outer join inside the update statement
UPDATE Customers, Recodes SET Customers.CustName = Replace([CustName],[char],[recode]);
This has the same effect as nesting all of the replace statements, and is a lot easier to manage.
This query grabs the 3 first characters and replace them with Blanks
Example: BO-1234
Output: 1234
BO: IIf(IsNumeric(Left([sMessageDetails],3)),[sMessageDetails],Replace([sMessageDetails],Left([sMessageDetails],3),""))