How to count equal values of the same element name [xQuery] - xquery

Here is an example:
`
<bracketQualifier>
<bracketSequenceNumber>1</bracketSequenceNumber>
</bracketQualifier>
<bracketQualifier>
<bracketSequenceNumber>1</bracketSequenceNumber>
</bracketQualifier>
<bracketQualifier>
<bracketSequenceNumber>1</bracketSequenceNumber>
</bracketQualifier>
`
What i need to do is if bracketSequenceNumber holds the same value trow an exception.
Number of elements is N there can be more than 3. How can i achieve this using xquery.
I tried something like this without success and i cant say i understand xQuery completley:
`
let $count := ( for $bracketSequenceNumber in $bracketQualifier/bracketSequenceNumber return count(bracketQualifier[#bracketSequenceNumber = $bracketSequenceNumber ])) return
if($GDSN_PriceSyncPriceSegmentTM/value ='250' and $count >= 1) then something
`

You can use
if (count(//bracketSequenceNumber)
!= count(distinct-values(//bracketSequenceNumber) then ...
If you actually want to find the duplicates, use group by in XQuery 3.1 to process each group of equal values and test whether the group size is 2 or more.

Related

CASE statement not Defining a Column Correctly Snowflake

I have a query in following format, used to perform COALESCE as well as define a new column using CASE statement.
SELECT ....
COALESCE(mm1,'missing') AS mm1,
COALESCE(mm2,'missing') AS mm2,
CASE WHEN mm1='false' AND mm2='false' THEN 'No-Proxy'
WHEN mm1 IN ('false','missing') AND mm2='true' THEN 'Good-Proxy'
WHEN mm1 ='true' AND mm2 IN ('false','missing') THEN 'Bad-Proxy'
WHEN ((mm1='true' AND mm2='true') OR (mm1='missing' AND mm2='missing')
OR (mm1='false' AND mm2='missing') OR (mm1='missing' AND mm2='false')) THEN 'Unknown'
END AS Proxy_Type,
As seen above when both mm1 and mm2 are originally NULL, we need to put value as Unknown for Proxy_Type. But when we run the query, we get unexpected output. Plz see screenshot.
Kindly advise on how to fix it.
It seems that "inline/lateral column aliasing" does not allow to "override" column at the same level:
CREATE OR REPLACE TABLE t
AS SELECT NULL AS mm1, NULL AS mm2;
Option 1: Using different column alias
SELECT
COALESCE(mm1,'missing') AS mm1_,
COALESCE(mm2,'missing') AS mm2_,
CASE WHEN mm1_='false' AND mm2_='false' THEN 'No-Proxy'
WHEN mm1_ IN ('false','missing') AND mm2_='true' THEN 'Good-Proxy'
WHEN mm1_ ='true' AND mm2_ IN ('false','missing') THEN 'Bad-Proxy'
WHEN ((mm1_='true' AND mm2_='true') OR (mm1_='missing' AND mm2_='missing')
OR (mm1_='false' AND mm2_='missing')
OR (mm1_='missing' AND mm2_='false')) THEN 'Unknown'
END AS Proxy_Type
FROM t;
-- MM1_ MM2_ PROXY_TYPE
--missing missing Unknown
Option 2: LATERAL JOIN and prefixing with subquery alias:
SELECT -- t.mm1, t.mm2,
s.mm1, s.mm2,
CASE WHEN s.mm1='false' AND s.mm2='false' THEN 'No-Proxy'
WHEN s.mm1 IN ('false','missing') AND s.mm2='true' THEN 'Good-Proxy'
WHEN s.mm1 ='true' AND s.mm2 IN ('false','missing') THEN 'Bad-Proxy'
WHEN ((s.mm1='true' AND s.mm2='true') OR (s.mm1='missing' AND s.mm2='missing')
OR (s.mm1='false' AND s.mm2='missing')
OR (s.mm1='missing' AND s.mm2='false')) THEN 'Unknown'
END AS Proxy_Type
FROM t,
LATERAL(SELECT COALESCE(t.mm1,'missing') AS mm1,COALESCE(t.mm2,'missing') AS mm2) s;
-- MM1 MM2 PROXY_TYPE
--missing missing Unknown
The ideal situation would be if we had additional keyword to distinguish between original column and calculated expression, kind of SAS - calculated.
SELECT
col,
col+10 AS col,
col,
calculated col
FROM t;
-- output
t.col/expression/t.col/expression
I’m guessing you are trying to use the re-defined values of mm1/mm2 in your case statement? If so then SQL doesn’t work like that, values don’t change within the same select statement so m1/m2 will have their starting values wherever they are referenced in the select statement.
One way round this is to use something like this:
COALESCE(mm1,'missing') AS mm1,
COALESCE(mm2,'missing') AS mm2,
CASE WHEN COALESCE(mm1,'missing') ='false' …

Count in xquery

I'm trying to solve this question but this code give me the result without counting it. What i mean it's that i need it to be a 13 but the result its divided by rows with a value of 1.
1
1
1
1
1
1
1
1
1
1
1
1
1
This is the question and this is what i have done.
List the number of countries that have a border (element ) in a country that has a Buddhist religion (element , value "Buddhist"). The correct query has to return the value 13.
for $var in /mondial/country
let $religion:=/mondial/country[religions="Buddhist"]/data(#id)
where $var /border/#country=$religion
return data (count($var/name)
This should get you there. I changed variable names to make things a bit more readable:
let $country := mondial/country
let $buddhist := $country[religions[./text()="Buddhist"]]/#id
return count($country[.//border[#country=$buddhist]])
Output:
13
Rather than returning the count for each item as you iterate, return each selected item and assign it to a variable, then you can get a count of the items of the sequence assigned to that variable:
let $names :=
for $var in /mondial/country
let $religion:= /mondial/country[religions="Buddhist"]/data(#id)
where $var/border/#country=$religion
return $var/name
return count($names)
You could also do this in a single XPath statement:
count(/mondial/country[border/#country=/mondial/country[religions="Buddhist"]/data(#id)])

Teradata : using case statement in Where clause

My question is about using case statement in where clause to check for date and assign values to columns. My sample code include.
select * from table
where
column 1 > 10 and
case when column 2 = 1
then
column 3<= 10 and column 4 between (1st day of prev month) and (prev month end) or column 5 = '8888-01-01'
else
column 4 between (1st day of this month) and (yesterday)
end ;
when I am running this code. I am getting 3706 syntax error:expected something in between field and '='.
How to fix this ?
A CASE statement will always return a value or NULL (if none of the conditions matches), so you can use it in your WHERE clause. There are a couple ways to format your CASE statement:
Format 1
CASE
WHEN <condition> THEN <some_expression>
WHEN <another_condition> THEN <another_expression>
ELSE <final_expression>
END
-- Example
CASE
WHEN col1 = 10 THEN 'Y'
WHEN col1 = 20 THEN 'N'
ELSE 'N/A'
END
Format 2
CASE <expression>
WHEN <value> THEN <expression>
WHEN <another_value> THEN <another_expression>
ELSE <final_expression>
END
-- Example
CASE col1
WHEN 10 THEN 'Y'
WHEN 20 THEN 'N'
ELSE 'NA'
END
I'm not sure what you're trying to do with your sample code, but it looks more like pseudo-code and will not work as-is. Your CASE statement is not formatted properly and your column references like column 1 will not work that way. If your column is actually named column 1, then you need to put double-quotes around it:
select * from table where "column 1" > 10
Can you please describe a little more clearly what exactly you are trying to do?
A CASE expression can't be used to create some kind of dynamic conditions. Write it as a bunch of AND/OR conditons:
select * from table
where
column 1 > 10 and
(
( column 2 = 1 and
(column 3<= 10 and column 4 between (1st day of prev month) and (prev month end) or column 5 = '8888-01-01')
)
or
column 4 between (1st day of this month) and (yesterday)
);
Double check the logic, the precedence of logical operators is
parenthesis
NOT
AND
OR

How to count number of elements with AQL?

I need to count elements that was in result of SQL query:
db._query('FOR v in visitors FILTER v.ip == "127.0.0.1" return COUNT(v.guid) ')
This request is return my a length of every GUID, but I need to get total number of GUIDs for example: 2.
You need to use the result of the query as input for the COUNT function, and then RETURN this result.
You can replace the RETURN value of the actual query by 1 for performance reasons:
RETURN COUNT(FOR v IN visitors FILTER v.ip == "127.0.0.1" RETURN 1)
Version from 2022!
FOR m IN messages
FILTER DATE_HOUR(m.date) == 3
COLLECT WITH COUNT INTO length
RETURN length

Pythonic way to increment and assign ids from dictionary

This seems to be a pretty common pattern:
for row in reader:
c1=row[0]
if ids.has_key(c1):
id1=ids.get(c1)
else:
currid+=1
id1=currid
ids[c1]=currid
I want to know if there is a better way to achieve this. As far as single line if statements go, I could do this much:
id1=ids.get(c1) if ids.has_key(c1) else currid+1
But then I'm stuck with incrementing currid and sticking if the else case was executed and sticking c->id1 into the dictionary if the if condition passed.
If the ids start from 0:
for row in reader:
id1 = ids.setdefault(row[0], len(ids))
(Aside: has_key is considered deprecated. Use x in d instead of d.has_key(x).)
If you don't mind changing how ids is defined, then you could go with this (all in the standard library):
ids = collections.defaultdict (itertools.count ().next)
Usage is then very simple:
print (ids["lol"])
currid += c1 not in ids
id1 = ids.setdefault(c1, currid)
Use this instead:
id1 = ids.get(cl, currid + 1)
A bit more pythonyc, with the same semantics:
for row in reader:
c1 = row[0]
if c1 not in ids:
currid += 1
ids[c1] = currid
id1 = ids[c1]

Resources