How to merge/combine arrays in pl/pgsql?
For example I have an 3 arrays: {1,2,3}, {"a","b","c"}, and {32,43,23}
After merging I need to get:
{{1,"a",32}, {2,"b",43}, {3,"c",23}}
My version of PostgreSQL is 9.0
It sounds like you want an n-argument zip function, as found in some functional languages and languages with functional extensions.
In this case you can't do exactly what yu want, because those arrays are of hetrogeneous types. PostgreSQL arrays must be of homogenous type, so this won't work. The desired result you show is an invalid array.
You could create an array of ROWs (anonymous records), or cast all the values to text.
For example:
SELECT array_agg(ROW(a,b,c))
FROM (
SELECT
unnest('{1,2,3}'::integer[]),
unnest('{"a","b","c"}'::text[]),
unnest('{32,43,23}'::integer[])
)
x(a,b,c);
will produce:
{"(1,a,32)","(2,b,43)","(3,c,23)"}
which is an array of three rowtypes cast to text. It will be awkward to work with because Pg has only very limited support for anonymous records; most importantly in this case you cannot cast a text value to RECORD(integer,text,integer), you must actually CREATE TYPE and cast to the defined type.
Because of that limitation, you may instead want to cast all the values to text and use a two-dimensional array of text. You'd expect to be able to do that with a simple array_agg, but frustratingly this fails:
SELECT array_agg(ARRAY[a::text,b,c::text])
FROM (
SELECT
unnest('{1,2,3}'::integer[]),
unnest('{"a","b","c"}'::text[]),
unnest('{32,43,23}'::integer[])
)
x(a,b,c);
producing:
ERROR: could not find array type for data type text[]
because array_agg doesn't support arrays as input. You need to define another variant of array_agg that takes a text[] input. I wrote one a while ago but can't find it now; I'll try to locate it and update if I find it. In the mean time you can work around it by casting the inner array to text:
SELECT array_agg(ARRAY[a::text,b,c::text]::text)
FROM (
SELECT
unnest('{1,2,3}'::integer[]),
unnest('{"a","b","c"}'::text[]),
unnest('{32,43,23}'::integer[])
)
x(a,b,c);
producing output like:
{"{1,a,32}","{2,b,43}","{3,c,23}"}
... OK, I haven't found the one I wrote, but here's an example from Erwin that does the job fine. Try this:
CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
,STYPE = anyarray
,INITCOND = '{}'
);
SELECT array_agg_mult(ARRAY[ARRAY[a::text,b,c::text]])
FROM (
SELECT
unnest('{1,2,3}'::integer[]),
unnest('{"a","b","c"}'::text[]),
unnest('{32,43,23}'::integer[])
)
x(a,b,c);
Output:
{{1,a,32},{2,b,43},{3,c,23}}
Related
xquery version "1.0-ml";
declare function local:sortit(){
for $i in ('a','e','f','b','d','c')
order by $i
return
element Result{
element N{1},
element File{$i}
}
};
local:sortit()
the above code is sample, I need the data in this format. This sorting function is used multiple places, and I need only element N data some places and only File element data at other places.
But the moment I use the local:sortit()//File. It removes the sorting order and gives the random output. Please let me know what is the best way to do this or how to handle it.
All these data in File element is calculated and comes from multiple files, after doing all the joins and calculation, it will be formed as XML with many elements in it. So sorting using index and all is not possible here. Only order by clause can be used.
XPath expressions are always returned in document order.
You lose the sorting when you apply an XPath to the sequence returned from that function call.
If you want to select only the File in sorted order, try using the simple mapping operator !, and then plucking the F element from the item as you are mapping each item in the sequence:
local:sortit() ! File
Or, if you like typing, you can use a FLWOR to iterate over the sequence and return the File:
for $result in local:sortit()
return $result/File
i am not a dot net programmer but need to migrate dotnet code to java .having issue understanding this follwing piece
Lets say specificTermical and ShipTo have latitutde property with different value so what happends when we use concat what will be the final value eg. 23.10+43.10 or something else
List<OrderDispatchItemDTO> locations =(List<OrderDispatchItemDTO>) msg.Details.Select(x => x.SpecificTerminal).Concat(msg.Details.Select(x => x.ShipTo));
The line of code that you provide returns a List of OrderDispatchItemDTO objects, that contains the values of both the SpecificTerminal and ShipTo properties of the Details objects.
It doesn't make any kind of calculation between the values of SpecificTerminal and ShipTo properties; it only adds both of them in a common list.
More detailed:
The Select method returns a new IEnumerable of the selected objects
And the Concat method concatenates the second collection into the first.
Concat is a string method. When you concatenate "23.10" and "43.10", it gives "23.1043.10". Therefore combining the two strings together.
To do any calculation in c#, you have to convert from strings data types to other mathematical data type that fits the say.
You may convert those two values to float and add them as shown below:
Float sum = Convert.ToFloat(23.10) + Convert.ToFloat(43.10);
I'm getting the XDMP-NOTANODE error when I try to run an XQuery in MarkLogic. When I loaded my xml documents I loaded meta data files with them. I'm a student and I don't have experience in XQuery.
error:
[1.0-ml] XDMP-NOTANODE: (err:XPTY0019) $article/article/front/article-meta/title-group/article-title -- xs:untypedAtomic("
") is not a node
Stack Trace
At line 3 column 77:
In xdmp:eval("(for $article in fn:distinct-values(/article/text()) ...", (), <options xmlns="xdmp:eval"><database>4206169969988859108</database> <root>C:\mls-projects\pu...</options>)
$article := xs:untypedAtomic("
")
1. (for $article in fn:distinct-values(/article/text())
2.
3. return (fn:distinct-values($article/article/front/article-meta/title-group/article-title)
4.
5.
Code:
(
for $article in fn:distinct-values(/article/text())
return (
fn:distinct-values($article/article/front/article-meta/title-group/article-title/text())
)
)
Every $article is bound to an atomic value (fn:distinct-values() returns a sequence of atomic values). Then you try to apply a path expression (using the / operator) on $article. Which is forbidden, as the path operator requires its LHS operator to be nodes.
I am afraid your code does not make sense enough for me to suggest you an actual solution. I can only pinpoint where the error is.
Furthermore, using text() at the end of a path is most of the time a bad idea. And if /article is a complex document, it is certainly not what you want. One of the text nodes you select (most likely the first one) is simply one single newline character.
What do you want to achieve?
Your $article variable is bound to an atomic value, not a node() from the article document. You can only use an XPath axis on a node.
When you apply the function distinct-values() in the for statement, it returns simple string values, not the article document or nodes from it.
You can probably make things work by using the values in a predicate filter like this:
for $article-text in fn:distinct-values(/article/text())
return
fn:distinct-values(/article[text()=$article-text]/front/article-meta/title-group/article-title/text())
Note: The above XQuery should avoid the XDMP-NOTANODE error, but there are likely easier (and more efficient) solutions for achieving your goal. If you were to post a sample of your document and describe what you are trying to achieve, we could suggest alternatives.
Bit of a wild guess, but you have two distinct-values in your code. That makes me think you want a unique list of articles, and then finally a unique list of article-title's. I would hope you already have unique articles in your database, unless you are explicitly attempting to de-duplicate them.
In case you just want the overall unique list of article titles, I would do something like:
distinct-values(
for $article in collection()/article
return
$article/front/article-meta/title-group/article-title
)
HTH!
I created the following table:
CREATE TABLE test (a INT,b INT);
After I inserted some data:
INSERT INTO test VALUES(1,2);
When I execute this SELECT:
SELECT cast(b as real) as x, a * b as y FROM teste
the fields "x" and "y" return with datatype TEXT. I'm using Delphi and SQLiteStudio 2.1.5, and both return the same datatype.
I need that field x being real and y being int.
Someone could help me?
Sqlite does not have column data type. It is just text. Based on your expression, it will try to do the conversion for you. For your math expression, you need to do a cast to give it is a hint to delphi to create your desired column type.
For me it's strange that in Sqlite, column types are "recommendations". But analyzing this I changed my program. I created the fields manually with correct type. So the program start to work.
The problem is when you open a query and the Delphi create the columns automatically. In this case, the columns with cast or with mathematical operation are created like text field.
User inputs a comma separated string and i d like to make a an associative array out of it as follows :
Input : 4,3,3,2,2
Output : Array{"0"=>4,"1"="3","2"=>3,"3"=>2,"4"=>2}
I can create an array by input.text.split(",");
But I d like to make it an associative array as above, how to do this?
Thanks.
Well, besides the fact that an array like the one you've got there is already 'associative' -- associated with numbers starting at 0. So:
yourArray[0] // will be 4
yourArray[3] // will be 2
If you want to associate with something else -- like strings -- then you might want to look into the Dictionary class.