Problem with string concatenation in Microsoft Access SQL query - sql

I have a table in an Access 2016 database which contains information for several locations. Each location is stored in one of three formats:
(type 1) standard US address with house number
(type 2) street intersection
(type 4) GPS coordinates only
(type 3 is not used in this database).
I'm trying to concatenate the individual field values into a single string with a query, so that I can display that string in a text box on a report. The format for type 1 is
[HouseNumber],[HouseNumberSuffix],[PrefixDirectional],[StreetName],[StreetType],[Qualifier],[City]
which would look like "100 E UNION ST, SOMERSET" for row 2 in the example below.
The format for type 2 is
[PrefixDirectional],[StreetName],[StreetType],'/',[XPrefixDirectional],[XStreetName],[XStreetType]
which should look like "N CENTER AVE/E MAIN ST" for row 3 in the example below.
The format for type 3 is
[LatitudeY],"|",[LongitudeX]
which should look like "39.957384|-78.824255" for row 6 in the example below.
Types 1 and 2 are geocoded by the application producing this data, so they also include Lat and Long values (when available), but I don't need to consider those fields when concatenating those rows. In this implementation, many of the fields contain null values. Since Microsoft Access doesn't support the CONCAT_WS() SQL function, I've been wracking my brain trying to find a workaround to concatenate the strings while eliminating extra spaces for the null fields.
Here is a sample of my table:
Table: Dim_Address
|AddressID|LocationType|HouseNumber|HouseNumberSuffix|PrefixDirectional|StreetName |StreetType|XPrefixDirectional|XStreetName|XStreetType|Qualifier|City |LatitudeY |LongitudeX |
|---------|------------|-----------|-----------------|-----------------|----------------|----------|------------------|-----------|-----------|---------|----------|------------|-------------|
|1 |1 | | | |<UNKNOWN> | | | | | | | | |
|12 |1 |100 | |E |UNION |ST | | | | |SOMERSET |40.0092574 |-79.078380702|
|37 |2 | | |N |CENTER |AVE |E |MAIN |ST | |SOMERSET |40.008420389|-79.078610673|
|6363 |4 | | | | | | | | | |SOMERSET |39.996243 |-79.034395 |
|9302 |2 | | | |MARKLETON SCHOOL|RD | |ROCKDALE |RD | |ROCKWOOD |39.908031106|-79.160141687|
|9725 |4 | | | | | | | | | |BERLIN |39.957384 |-78.824255 |
|8282 |1 |222 | | |MAIN |ST | | | |APT 13 |MEYERSDALE|39.814387822|-79.026677269|
|55233 |1 |2110 |1/2 | |GRAHAM |AVE | | | | |WINDBER |40.230844268|-78.82551539 |
[AddressID], [LocationType], and [HouseNumber] are integers; [LatitudeY] and [LongitudeX] are doubles; the remaining fields are all strings.
And here is the code I'm attempting to use in my query:
SELECT
Switch(
[LocationType]=1,((CStr([HouseNumber])+' ') & ([HouseNumberSuffix]+' ') & ([PrefixDirectional]+' ') & ([StreetName]+' ') & [StreetType] & (', '+[Qualifier]) & (', '+[VenueName])),
[LocationType]=2,(([PrefixDirectional]+' ') & ([StreetName]+' ') & ([StreetType]+' ') & ('/') & ([XPrefixDirectional]+' ') & ([XStreetName]+' ') & ([XStreetType]+' ')),
[LocationType]=4,(CStr([LatitudeY]) & ' | ' & CStr([LongitudeX]))
) AS LocationConcatenation
FROM Dim_Address;
Here are the results I get when I run the query on the table above:
|LocationConcatenation |
|-------------------------------|
|#Error |
|100 E UNION ST, SOMERSET |
|#Error |
|#Error |
|#Error |
|#Error |
|222 MAIN ST, APT 13, MEYERSDALE|
|2110 1/2 GRAHAM AVE, WINDBER |
It works exactly as expected for type 1, except for row 1. On another post in this forum (CONCAT equivalent in MS Access), someone suggested that using + for concatenation would create empty strings if used to concatenate a string with another null, so I tried that, but Row 1 is still giving me grief. For types 2 or 4, the query doesn't work at all. Could anyone shed some light on where I'm making the mistake? I'm fairly familiar with SQL but am frustrated with the limited way that Access supports it. (BTW, <UNKNOWN> is used by the program that created this data as a placeholder for an address by default if an actual address is not entered by the user, so it appears in many records in a related table).

You can implement the equivalent of concat_ws() in MS Access using nz(), ltrim() and conditional logic:
select Switch(LocationType = 1,
ltrim(nz(" " + CStr(HouseNumber), "") +
nz(" " + HouseNumberSuffix, "") +
nz(" " + PrefixDirectional, "") +
nz(" " + StreetName, "") +
nz(" " + StreetType, "") + ", " &
nz(" " + Qualifier, "") + ", "
nz(" " + VenueName, "")
),
. . .
)

Related

Check string for substring existence

How can I check whether a certain substring (for instance 18UT) is part of a string in a column?
Redshifts' SUBSTRING function allows me to "cut" a certain substring based on a starting index + length of the subtring, but not check whether a specific substring exists is in the column's value.
Example:
+------------------+
| col |
+------------------+
| 14TH, 14KL, 18AB |
| 14LK, 18UT, 15AK |
| 14AB, 08ZT, 18ZH |
| 14GD, 52HG, 18UT |
+------------------+
Desired result:
+------------------+------+
| col | 18UT |
+------------------+------+
| 14TH, 14KL, 18AB | No |
| 14LK, 18UT, 15AK | Yes |
| 14AB, 08ZT, 18ZH | No |
| 14GD, 52HG, 18UT | Yes |
+------------------+------+
Here is one option:
select col,
case when ', ' || col || ', ' like '%, 18UT, %' then 'yes' else 'no' end has_18ut
from mytable
While this will solve your immediate, problem, it should be note that storing delimited lists in a database table is bad practice, and should be avoided. Each value should go to a separate row instead.

Adding space at the end of a line in Gherkin

My question is:
I have a datatable with some values. and i want to the end of one of the values to have a whitespace.
eg.
| Name | Surname | Statement |
| AO | PO | This is a statement |
i want to add a whitespace after the word statement. How can i do that?
Depending on your stepdefinitions (using {string}, {word} or the ^...$ notation) you can do
| Name | Surname | Statement |
| AO | PO | "This is a statement " |
Or use the whitespace character
| Name | Surname | Statement |
| AO | PO | This is a statement\s |

SQL padding 0 to the left of a number in string

I am a beginner in SQL language and I am using postgre sql and doing little exercices to learn. I have a column of strings named acronym from a destination table:
DO1
ES1
ES2
FR1
FR10
FR2
FR3
FR4
FR5
FR6
FR7
FR8
FR9
GP1
GP2
IN1
IN2
MU1
RU1
TR1
UA1
I would like to add a padding zero for acronym numbers that have only one digit, output:
DO01
ES01
ES02
FR01
FR02
FR03
FR04
FR05
FR06
FR07
FR08
FR09
FR10
GP01
GP02
IN01
IN02
MU01
RU01
TR01
UA01
How can I get to the left of the first number in the string? There is some regex I think but I did not figure it out
You can use the rpad() function to add characters to the end of the value:
select rpad(col, '0', 4)
In your case, though, you want a value in-between. On simple method is -- assuming that the first two characters are strings -- is:
(case when length(col) = 3
then left(col, 2) || '0' || right(col, 1)
else col
end)
Another possibility is using regexp_replace():
regexp_replace(col, '^([^0-9]{2})([0-9])$', '\10\2')
Both of these assume that the strings to be padded are three characters, which is consistent with your data. It is unclear what you want for other lengths.
try with below:
to_char() function
select to_char(column1, 'fm000') as column2
from Test_table;
fm "fill mode"prefix avoids leading spaces in the resulting var char.
000 it defines the number of digits you want to have.
You can use string functions like lpad(), substr(), left():
select
concat(left(columnname, 2), lpad(substr(columnname, 3), 2, '0')) result
from tablename
See the demo.
Results:
| result |
| ------ |
| DO01 |
| ES01 |
| ES02 |
| FR01 |
| FR10 |
| FR02 |
| FR03 |
| FR04 |
| FR05 |
| FR06 |
| FR07 |
| FR08 |
| FR09 |
| GP01 |
| GP02 |
| IN01 |
| IN02 |
| MU01 |
| RU01 |
| TR01 |
| UA01 |

SQL Query for Pivoting data in MS-Access

I have a table with three fields: ticketNumber, attendee and tableNumber.
e.g.
ticketNumber | attendee | tableNumber
------------ | -------- | -----------
A1 | alex | 3
A2 | bret | 2
A3 | chip | 1
A4 | dale | 2
A5 | eric | 2
A6 | finn | 3
I'd like to generate a table with each tableNumber as a field and the list of names sitting at that tableNumber.
1 | 2 | 3
-----|------|-----
chip | bret | alex
| dale | finn
| eric |
The query I've been working on is:
transform attendee
select attendee
from registration
group by tableNumber, name
pivot tableNumber
This gives me:
attendee | 1 | 2 | 3
---------|------|------|-----
chip | chip | |
bret | | bret |
dale | | dale |
eric | | eric |
alex | | | alex
finn | | | finn
I know how to get the table I require using PivotTableView but I'd like to know how to do it with a query so that I can use it in a code I'm working on. I'm unsure of how I can write this query without having to select a field (in my case, select attendee). Also is it possible to generate the table without the empty cells?
Thank you :)
The table needs a unique identifier field that will properly sort and I don't think the ticketNumber can be relied on for that. An autonumber should serve. Then try:
TRANSFORM First(Table1.attendee) AS FirstOfattendee
SELECT DCount("*","Table1","tableNumber=" & [tableNumber] & " AND ID<" & [ID])+1 AS RowSeq
FROM Table1
GROUP BY DCount("*","Table1","tableNumber=" & [tableNumber] & " AND ID<" & [ID])+1
PIVOT Table1.tableNumber;

How to tokenize a SQL Server column for use in frequency distribution in SSAS

I have a field in my table called Description . Here is an examples of a few records:
+-----------+------------+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------+------------+---------+---------+-------------------+---------------+-------------+-------------+
| RecordKey | RecordType | Price | Description | RecordNumber | DiscsinSet | Country | Company | DigitalAnalogCode | Genre | UPC | datecreated |
+-----------+------------+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------+------------+---------+---------+-------------------+---------------+-------------+-------------+
| 100488 | CD | 5.99 | Korngold, Honegger, Verdi, Wagner, Puccini, Leoncavallo, Giordano: Opera Arias + 'I Know Where I'm Going'. (Ellen Faull, soprano. Taken from the Sylvan Levin Opera Concert Broadcasts of 1951 & 1952. Total time: 65'47') | VAIA 1173 | 1 | AMERICA | VAI | M | Songs & Arias | 89948117322 | 42:38.4 |
| 100503 | CD | 11.98 | Puccini, Madama Butterfly. (Kirsten, Barioni, Nadell et al. New Orleans Opera/ Cellini. Rec.3/60) | VAIA 1054-2 | 2 | AMERICA | VAI | A | Opera | 89948105428 | 42:38.4 |
| 100516 | MV | 8.99 | Brahms, 8 Gypsy Songs. Schumann, 2 Short Gypsy Songs. Liszt, The 3 Gypsies. Verdi, The Gypsy Woman. J.Strauss, 'Gypsy Baron'- Song of Sapphi + Other Gypsy Songs by Balakirev, Varlamov, Tchaikovsky, Verstovskij, Dvorak & Lehar. (Ljuba Kazarnovskaya, soprano w.Mark Morash, piano. Rec.Moscow, 2/19/98) | 69503 | 1 | AMERICA | VAI | S | NULL | 89948695035 | 42:38.4 |
+-----------+------------+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------+------------+---------+---------+-------------------+---------------+-------------+-------------+
Apologies, if it is difficult to read, but the description field has a lot of text.
I would like to create a frequency distribution of every word in this field.
The output I would like would look something like this:
+-----------+-------+
| word | count |
+-----------+-------+
| Beethoven | 344 |
| Strauss | 34533 |
| Piano | 3 |
| Webber | 34 |
+-----------+-------+
If it makes more sense, could you point me in the right direction on how this can be achieved with SSAS?
If you have a separate list of valid words, you can just do:
select w.word, count(*)
from mytable t join
words w
on ', ' + w.word + ', ' like '%, ' + t.description + ', %'
group by w.word;
If you don't, then look around the web for a split() function. You can then use cross apply for something like:
select w.value, count(*)
from mytable t cross apply
(select *
from split(t.description, ', ')
) w
group by w.value;
If you have control over the data structure, then naughty, naughty. SQL has this wonderful data structure for storing lists. It is called a table. It is not called a string. You should be using a junction table -- if you have control. One doesn't always have control over such issues, though.