Translating strings postgres - string

I'm trying to translate 2 types of data using only postgres SQL
I've got a column "type" that may contains the kind of data.
type is a string column and may have "ACTUAL" or "OLD" values
+-type-+
+ACTUAL+
+OLD +
+------+
when I show the list with a lot of other joins I would like to show only "A" or "O" values
I couldnt find other way to do this than:
SELECT replace(replace(mytable.type, 'ACTUAL', 'A'),'OLD', 'O');
With that I can replace the text the way I need,
but I was looking for some more function using an array as parameter.
something like a cross-reference simple function:
translate(['ACTUAL','OLD'], ['A','O'])
Does anyone know a way to do this that doesn't use SQL views and neither needs another table like joining the results of this value with other table?
Thanks in advance,
Andre

I would use something like CASE...
SELECT
(CASE type
WHEN 'ACTUAL' THEN 'A'
WHEN 'OTHER' THEN 'O'
ELSE '?' END)
FROM
Using this method, you can return whatever you want based on whatever criteria you want, not just sub-stringing.

Related

How to search values in excel and assigned a particular value based on logic (Based on RIGHT, IF, OR condition)

Trying to extract the values from the right side (single digit) of the ID column and based on that assigning "A","B","C",""
I have tried with the below logic, but not getting the expected result. Can anyone suggest me in this?
=IF(RIGHT(A2,1)=OR(1,2,6),"A",IF(OR(3,7,9),"B",IF(OR(4,8,0),"C",IF(5,"D",""))))
Excel Table:
ID Value
AB1ZX0 C
BC5SD2 A
FR3WDX
CA4EG7 B
There are a couple issues with your original try:
Since the cells are text based, you need quotes around the number you are testing (...="1" instead of ...=1).
You need to reference what you are testing (the RIGHT(A2,1)) each time you use IF.
You can not use OR like that; it's return is boolean so you would need to do something like =IF(OR(RIGHT(A2,1)="1", RIGHT(A2,1)="2", RIGHT(A2,1)="6"), "A", ... to make it work.
Instead, the below should do the trick, though it is a little messy and verbose:
=CONCAT(IF(RIGHT(A5,1)={"1","2","6"}, "A",
IF(RIGHT(A5,1)={"3","7","9"}, "B",
IF(RIGHT(A5,1)={"4","8","0"}, "C",
IF(RIGHT(A5,1)="5", "D","")))))
You could use a SWITCH to make a clean formula. But as already noted, the last character in ID is text and needs to be compared to text, not numbers. Here is the SWITCH based solution:
=SWITCH(RIGHT(A2,1),
"1","A","2","A","6","A",
"3","B","7","B","9","B",
"4","C","8","C","0","C",
"5","D",
"")

How do I conditionally add a new line and tabs in Excel?

I have a list of values id, name, category, description and a variable amount of keyword values; between 0 and 18 for each row. I want to create a list of those values in the form of:
(id, 'keyword')
, (id, 'keyword')
Where the list only increments if there is a keyword to go with the identifier. This is meant to be an easy manual list for a SQL INSERT statement.
I realize that I can use &CHAR(9) for inserting tabs and &CHAR(10) for inserting new lines, and thus my sequence for proper tabulation is &CHAR(10)&CHAR(9)&CHAR(9) for each new entry.
=IF(G2<>"",CONCATENATE("(",A2,", '",UPPER(G2),"')"),"")
&CHAR(10)&CHAR(9)&CHAR(9)&
IF(H2<>"",CONCATENATE("(",A2,", '",UPPER(H2),"')"),"")
I've tried several different combinations such as:
=IF(G2<>"",CONCATENATE("(",A2,", '",UPPER(G2),"')"),"")+
IF(H2<>"",CHAR(10)&CHAR(9)&CHAR(9)&CONCATENATE("(",A2,", '",UPPER(H2),"')"),"")
and
=IF(G2<>"",CONCATENATE("(",A2,", '",UPPER(G2),"')",CHAR(10),CHAR(9),CHAR(9)),"")+
IF(H2<>"",CONCATENATE("(",A2,", '",UPPER(H2),"')"),"")
and
=IF(G2<>"",CONCATENATE("(",A2,", '",UPPER(G2),"')"),"")+
IF(H2<>"",CONCATENATE(CHAR(10),CHAR(9),CHAR(9),"(",A2,", '",UPPER(H2),"')"),"")
which all give errors in calculation. Has anyone else been dying to know how to do this and had this kind of frustration? Does anyone have a solution to this?
I actually figured this out within an hour of posting, but neglected to post the solution here in case anyone else wanted to know.
You have to CONCATENATE the whole series of IF blocks and add the CHAR(10) and CHAR(9)s to the inner CONCATENATE blocks, like so:
=CONCATENATE(IF(G2<>"",CONCATENATE("(",A2,", '",UPPER(G2),"')"),""),
IF(H2<>"",CONCATENATE(CHAR(10),CHAR(9),CHAR(9),"(",A2,", '",UPPER(H2),"')"),""))
Thanks,
-C§

Display logic based on field's value length

Is it posible to create a display logic condition with the size or length of a field's value?
For example: #upc.length#<13 or anything like that?
I have tried it that way but it is not working. I would appreciate if anyone knows the logical operators for this. In the openbravo howtos is not very explanative.
Thanks.
As suggested in the comment, use an auxiliary input.
Auxiliary Input
Name : upcLength
SQL
select (case when length (upc) > 13 then 'Y' else 'N' end) as length
from table where table_id = #table_id#
In Windows, Tabs and Fields, for a field add the display logic.
#upcLength#='Y'
PS: Assumed DB Postgres.

Using SQL "IN" Function in Excel

Is there an "IN" type function like the one used in sql that can be used in excel? For example, if i am writing an If statement in excel and I want it to check the contents of a cell for 5 different words can i write something like:
=If(A1=IN("word1","word2","word3","word4","word5"),"YES","NO")
You could use MATCH :
=MATCH(A1, {"word1","word2","word3","word4","word5"}, 0)
which will return the index of the matching item in the array list. The trailing 0 means it should be an exact match. It will return #N/A if it isn't there, so you can tag a IF(ISNA( onto the front to make it behave like your "IN":
=IF(ISNA(MATCH(A1, {"word1","word2","word3","word4","word5"}, 0)),"NO","YES")
Note the change in order of the "YES" and "NO"
=IF(OR(A1={"word1","word2","word3","word4","word5"}),"YES","NO")
I think an improvement on
=IF(OR(A1={"word1","word2","word3","word4","word5"}),"YES","NO")
would be to use
=IF(OR(A1={"word1","word2","word3","word4","word5"}),A1,"NO");
which is more like the SQL's IN clause.
Use the OR function. It operationes very similiar to what you are looking for.
IF(OR(A1="word1",A1="word2",A1="word3")=TRUE,"Yes","No")
Also doesn't require the ctrl+shift+enter when using.

Quick SQL question

Working on postgres SQL.
I have a table with a column that contains values of the following format:
Set1/Set2/Set3/...
Seti can be a set of values for each i. They are delimited by '/'.
I would like to show distinct entries of the form set1/set2 and that is - I would like to trim or truncate the rest of the string in those entries.
That is, I want all distinct options for:
Set1/Set2
A regular expression would work great: I want a substring of the pattern: .*/.*/
to be displayed without the rest of it.
I got as far as:
select distinct column_name from table_name
but I have no idea how to make the trimming itself.
Tried looking in w3schools and other sites as well as searching SQL trim / SQL truncate in google but didn't find what I'm looking for.
Thanks in advance.
mu is too short's answer is fine if the the lengths of the strings between the forward slashes is always consistent. Otherwise you'll want to use a regex with the substring function.
For example:
=> select substring('Set1/Set2/Set3/' from '^[^/]+/[^/]+');
substring
-----------
Set1/Set2
(1 row)
=> select substring('Set123/Set24/Set3/' from '^[^/]+/[^/]+');
substring
--------------
Set123/Set24
(1 row)
So your query on the table would become:
select distinct substring(column_name from '^[^/]+/[^/]+') from table_name;
The relevant docs are http://www.postgresql.org/docs/8.4/static/functions-string.html
and http://www.postgresql.org/docs/8.4/static/functions-matching.html.
Why do you store multiple values in a single record? The preferred solution would be multiple values in multiple records, your problem would not exist anymore.
Another option would be the usage of an array of values, using the TEXT[] array-datatype instead of TEXT. You can index an array field using the GIN-index.
SUBSTRING() (like mu_is_too_short showed you) can solve the current problem, using an array and the array functions is another option:
SELECT array_to_string(
(string_to_array('Set1/Set2/Set3/', '/'))[1:2], '/' );
This makes it rather flexible, there is no need for a fixed length of the values. The separator in the array functions will do the job. The [1:2] will pick the first 2 slices of the array, using [1:3] would pick slices 1 to 3. This makes it easy to change.
If they really are that regular you could use substring; for example:
=> select substring('Set1/Set2/Set3/' from 1 for 9);
substring
-----------
Set1/Set2
(1 row)
There is also a version of substring that understands POSIX regular expressions if you need a little more flexibility.
The PostgreSQL online documentation is quite good BTW:
http://www.postgresql.org/docs/current/static/index.html
and it even has a usable index and sensible navigation.
If you want to use .*/.* then you'd want something like substring(s from '[^/]+/[^/]+'), for example:
=> select substring('where/is/pancakes/house?' from '[^/]+/[^/]+');
substring
-----------
where/is
(1 row)

Resources