Can't get children multiply values using XMLTABLE - xml-parsing

guys, i'm trying to get values from the next query
SELECT X.val, X.tdate
FROM
XMLTABLE ('$d/IRR' passing XMLPARSE(DOCUMENT '<IRR><value>2</value><tdate>2014-06-05</tdate><value>4</value><tdate>2014-08-05</tdate></IRR>') as "d"
COLUMNS
val DOUBLE PATH './value',
tdate DATE PATH './tdate' ) AS X;
but I always get the error:
An expression of data type "( item(), item()+ )" cannot be used when
the data type "DATE" is expected in the context
at the same time everything works fine if there is only one value and date like
SELECT X.val, X.tdate
FROM
XMLTABLE ('$d/IRR' passing XMLPARSE(DOCUMENT '<IRR><value>2</value><tdate>2014-06-05</tdate></IRR>') as "d"
COLUMNS
val DOUBLE PATH './value',
tdate DATE PATH './tdate' ) AS X;
And as I understand here it's because XMLTABLE waits only for 1 value and it cann't parse the doc if there are few of them
What's more it works fine if there is only 1 column need to be returned like this even though there are a few values:
SELECT X.tdate
FROM
XMLTABLE ('$d/IRR/tdate' passing XMLPARSE(DOCUMENT '<IRR><value>2</value><tdate>2014-06-05</tdate><value>4</value><tdate>2014-08-05</tdate></IRR>') as "d"
COLUMNS
tdate DATE PATH '.' ) AS X;
So this query returns both dates.
tdate
2014-06-05
2014-08-05
So is there any way to return both columns with multiply values in the same query?
e.g.
val tdate
2 2014-06-05
4 2014-08-05
Note: that is the representation of the xml document which is passed in my procedure (it could contain more than 2 values)
<IRR><value>2</value><tdate>2014-06-05</tdate><value>4</value><tdate>2014-08-05</tdate></IRR>

XMLTABLE() can return a special ordinality column, containing the sequential number of each row. You can use it to do something like:
WITH t(x) AS (VALUES XMLPARSE(DOCUMENT '<IRR><value>2</value><tdate>2014-06-05</tdate><value>4</value><tdate>2014-08-05</tdate></IRR>'))
SELECT x1.value, x2.tdate
FROM
t,
XMLTABLE ('$X//value'
COLUMNS
value INT PATH '.',
idx FOR ORDINALITY) AS X1,
XMLTABLE ('$X//tdate'
COLUMNS
tdate DATE PATH '.',
idx FOR ORDINALITY) AS X2
WHERE x1.idx = x2.idx
ORDER BY 2
This assumes that the XML parser preserves the element order, which, although not explicitly documented, seems to be the case with all parsers I've worked with.
Ideally you should rethink your XML schema, for example, passing tdate as an attribute of value (or vice versa).

Related

Sorting rows in a Grid column of String type based on corresponding integer values

I have the following structure for a Grid and wanted to know how to sort a column based on the Integer values of the Strings. The data provider is not flexible to change, so I have to sort with some kind of intermediary step:
Grid<String[]> grid = new Grid<>();
...
grid.addColumn(str -> str[columnIndex]).setHeader("sample").setKey("integercolumn").setSortable(true);
...
GridSortOrder<String> order = new GridSortOrder<>(grid.getColumnByKey("integercolumn"), SortDirection.DESCENDING);
grid.sort(Arrays.asList(order));
This sorts two digit numbers properly but not one digit or 3+.
You can define a custom comparator on the column that is used for sorting its values. In your case the comparator needs to extract the column-specific value from the array, and then convert it to an int:
grid.addColumn(row -> row[columnIndex])
.setHeader("sample")
.setKey("integercolumn")
.setSortable(true)
.setComparator(row -> Integer.parseInt(row[columnIndex]));
See https://vaadin.com/docs/latest/components/grid/#specifying-the-sort-property.

convert neo4j cypher list of integer not working

I have list property [1,2,2,0]. The value is the list default to type of long. To convert to a list of type integer I am using
apoc.convert.toIntList([1,2,2,0])
but the result is still a list of type long.....however
apoc.convert.toStringList([1,2,2,0])
does result in a list of strings. This my query:
MERGE (bs:Bslot {date: $date})
ON CREATE
SET bs.slots = [1,2,2,0]
RETURN {slots: apoc.convert.toIntList(bs.slots)}
What am I doing wrong here?
It is working as expected; see below example:
WITH [1,2,2,0.99] as slots
RETURN {slots: apoc.convert.toIntList(slots)}
Result:
╒════════════════════════════════════════╕
│"{slots: apoc.convert.toIntList(slots)}"│
╞════════════════════════════════════════╡
│{"slots":[1,2,2,0]} │
└────────────────────────────────────────┘
Notice that 0.99 (float) becomes an integer.
In your example; MERGE will not update slots property when that node Bslot with date equals $date. It is because it will only set the value of slots to [1,2,2,0] if that node is new (create).

Writing variable-length sequence to a compound array

I am using compound datatypes with h5py, with some elements being variable-length arrays. I can't find a way to set the item. The following MWE shows 6 various ways to do that (sequential indexing — which would not work in h5py anyway, fused indexing, read-modify-commit for columns/rows), neither of which works.
What is the correct way? Why is h5py saying Cannot change data-type for object array when writing integer list to int32 list?
with h5py.File('/tmp/test-vla.h5','w') as h5:
dt=np.dtype([('a',h5py.vlen_dtype(np.dtype('int32')))])
dset=h5.create_dataset('test',(5,),dtype=dt)
dset['a'][2]=[1,2,3] # does not write the value back
dset[2]['a']=[1,2,3] # does not write the value back
dset['a',2]=[1,2,3] # Cannot change data-type for object array
dset[2,'a']=[1,2,3] # Cannot change data-type for object array
tmp=dset['a']; tmp[2]=[1,2,3]; dset['a']=tmp # Cannot change data-type for object array
tmp=dset[2]; tmp['a']=[1,2,3]; dset[2]=tmp # 'list' object has no attribute 'dtype'
When working with compound datasets, I've discovered it's best to add all row data in a single statement. I tweaked your code and to show how add 3 rows of data (each of different length). Note how I: 1) define the row of data with a tuple; 2) define the list of integers with np.array(); and 3) don't reference the field name ['a'].
with h5py.File('test-vla.h5','w') as h5:
dt=np.dtype([('a',h5py.vlen_dtype(np.dtype('int32')))])
dset=h5.create_dataset('test',(5,),dtype=dt)
print (dset.dtype, dset.shape)
dset[0] = ( np.array([0,1,2]), )
dset[1] = ( np.array([1,2,3,4]), )
dset[2] = ( np.array([0,1,2,3,4]), )
For more info, take a look at this post on the HDF Group Forum under HDF5 Ancillary Tools / h5py:
Compound datatype with int, float and array of floats

SQL in AR searching if an element is not within a column array

date = Date.today
Subscription.joins(:cart).where("'#{date.beginning_of_week(:sunday).to_s}' != ANY (carts.skipped_weeks)")
The column skipped_weeks on Cart is an array of dates like ["2017-04-10", "2017-04-17"]
I am running the above query and still receiving and records that have a date included on the cart.skipped_weeks column array, I only want records that do not include that date in the skipped_weeks array.
PostgreSQL supports all as well as any:
9.23.4. ALL (array)
expression operator ALL (array expression)
The right-hand side is a parenthesized expression, which must yield an array value. The left-hand expression is evaluated and compared to each element of the array using the given operator, which must yield a Boolean result. The result of ALL is "true" if all comparisons yield true (including the case where the array has zero elements). The result is "false" if any false result is found.
Saying:
where('? != all(carts.skilled_weeks)', date.beginning_of_week(:sunday))
would probably be a more readable match for your intended logic.
Subscription.joins(:cart).where("NOT '#{date.beginning_of_week(:sunday).to_s}' = ANY (carts.skipped_weeks)")
Here is the correct form

Max() in LINQ Query

I have a Column with DataType as Nvarchar(max)
Sample Records:
Advisor_Code
9001
9002
9003
100001
100001
9011
I have tried this Query :
var code = (from a in db.advisor_Registration select a ).Max(a=>a.advisor_Code);
It Returns 9011 but max Number is 100001 .
How to fix it
Since one of the tags is entity-framework I assume it should be translatable into SQL. If you use e.g. Convert.ToInt32 in the LINQ statement, this won't succeed.
A common way to get the "numeric" max out of strings without conversion is to order by length and then by string:
var max = myquery.OrderByDescending(x => x.Length)
.ThenByDescending (x => x)
.First();
where myquery could be any query against a DbSet that returns strings. Of course the results will be meaningless if any of the strings is not numeric.
You can only perform a MAX function with your expected result on a numeric field. nvarchar(max) is not a numeric field. You would have to convert the strings to a long, for example, then take the MAX for MAX to work as you are expecting.

Resources