Multiple Wildcards/Filters for SQL - sql

I am attempting to only retrieve Business Unit specific information from a large datamart, and would like to structure my query to eliminate unrelated DepartmentIDs.
In plainspeak, the end goal is to filter on ALL DepartmentIDs starting with "AN" and ending in 0, P, A, N, R, V, C, L, W, E, or Y.
Currently the query starts with:
FROM bbms_tpirc.dbo.LaborDetailByName LaborDetailByName
WHERE (LaborDetailByName.post_year='2016') AND
(LaborDetailByName.center_id='APEEN') AND
(LaborDetailByName.loan Like 'AN%')
but I am struggling with the next section.
Using another AND (LaborDetailByName.loan Like '%0', '%P') etc doesn't return anything in the dataset. Might I be overfiltering, or simply forgetting an argument?

You can replace your filter clause
(LaborDetailByName.loan Like 'AN%')
with
(LaborDetailByName.loan Like 'AN%[OPANRVCLWEY]')

In SQL Server or MySQL, you can use RIGHT():
AND RIGHT(LaborDetailByName.loan,1) in ('0','P','A','N','R','V','C','L','W','E','Y')

Related

sum of setof in prolog

I have this predicate to get the sum of the length of all borders of a country. I could solve it with findall but I have to use setof. My facts look like this:
borders(sweden,finland,586).
borders(norway,sweden,1619).
My code
circumference(C, Country) :-
findall(X, ( borders(Country, _, X) ; borders(_, Country, X)), Kms),
sum_list(Kms, C).
You cannot find the sum using bagof directly, all you can do is make a list and then sum that list (but you knew that already). In SWI-Prolog there is library(aggregate) that does the bagging and the summing for you. With the facts you have, you would write:
?- aggregate(sum(X), Y^( borders(Y, sweden, X) ; borders(sweden, Y, X) ), Circumference).
Circumference = 2205.
If you instead must obey the whims of your instructor and type "bagof" yourself, or if you are not allowed to use a modern, open source, comprehensive Prolog implementation, you can use the same approach with bagof and manually build the list before summing it:
?- bagof(X, Y^( borders(Y, sweden, X) ; borders(sweden, Y, X) ), Borders).
Borders = [1619, 586].
For reasons that are lost in the mists of time the funny thing with the Var^Goal that you see in both aggregate and bagof is called "existentially qualifying the variables in Goal". You might also read that "^ prevents binding Var in Goal". I cannot explain what this really means.
I ended up using this:
circumference(Z, Country) :- setof(X, Q^(borders(Q,Country,X);borders(Country,Q,X)),Border),
sum_list(Border,Z).
% Adds the numbers in a list.
sum_list([], 0).
sum_list([H|T], Sum) :-
sum_list(T, Rest),
Sum is H + Rest.

Trying to explode an array with unnest() in Presto and failing due to extra column

I have data from a query that looks like this:
SELECT
model_features
FROM some_db
which returns:
{
"food1": 0.65892159938812,
"food2": 0.90786880254745,
"food3": 0.88357985019684,
"food4": 0.99999821186066,
"food5": 0.99237471818924,
"food6": 0.62127977609634
}
{
"food4": 0.9999965429306,
"text1": 0.82206630706787
}
...
etc.
What I am eventually trying to do is simply get a count of each of the "food1", "food2" features,
but to do so (i think) I need to trim out the unnecessary numeric data. I'm at a loss as to how to do this, as everytime I try to simply unnest
SELECT
t.concepts
FROM some_db
CROSS JOIN UNNEST(model_features) AS t(concepts)
I get this error:
Column alias list has 1 entries but 't' has 2 columns available
Anyone mind pointing me in the right direction?
Solved this for myself: the issue was I needed to avoid dropping the second column of information in order for the query to execute. This may not be the canonical best way to approach, but it worked:
SELECT
t.concepts,
t.probabilities
FROM some_db
CROSS JOIN UNNEST(model_features) AS t(concepts,probabilities)

Apex parse error when creating SQL query with sql function

I have the following function:
CREATE OR REPLACE FUNCTION calc_a(BIDoctor number) RETURN number
IS
num_a number;
BEGIN
select count(NAppoint)
into num_a
from Appointment a
where BIDoctor = a.BIDoctor;
RETURN num_a;
END calc_a;
What we want is adding a column to a report that shows us the number of appointments that doc have.
select a.BIdoctor "NUM_ALUNO",
a.NameP "Nome",
a.Address "Local",
a.Salary "salary",
a.Phone "phone",
a.NumberService "Curso",
c.BIdoctor "bi",
calc_media(a.BIdoctor) "consultas"
FROM "#OWNER#"."v_Doctor" a, "#OWNER#"."Appointment" c
WHERE a.BIdoctor = c.BIdoctor;
and we got this when we are writing the region source on apex.
But it shows a parse error, I was looking for this about 2 hours and nothing.
Apex shows me this:
PARSE ERROR ON THE FOLLOWING QUERY
This is probably because of all your double quotes, you seem to have randomly cased everything. Double quotes indicate that you're using quoted identifiers, i.e. the object/column must be created with that exact name - "Hi" is not the same as "hi". Judging by your function get rid of all the double quotes - you don't seem to need them.
More generally don't use quoted identifiers. Ever. They cause far more trouble then they're worth. You'll know when you want to use them in the future, if it ever becomes necessary.
There are a few more problems with your SELECT statement.
You're using implicit joins. Explicit joins were added in SQL-92; it's time to start using them - for your future career where you might interact with other RDBMS if nothing else.
There's absolutely no need for your function; you can use the analytic function, COUNT() instead.
Your aliases are a bit wonky - why does a refer to doctors and c to appointments?
Putting all of this together you get:
select d.bidoctor as num_aluno
, d.namep as nome
, d.address as local
, d.salary as salary
, d.phone as phone
, d.numberservice as curso
, a.bidoctor as bi
, count(nappoint) over (partition by a.bidoctor) as consultas
from #owner#.v_doctor a
join #owner#.appointment c
on d.bidoctor = a.bidoctor;
I'm guessing at what the primary keys of APPOINTMENT and V_DOCTOR are but I'm hoping they're NAPPOINT and BIDOCTOR respectively.
Incidentally, your function will never have returned the correct result because you haven't limited the scope of the parameter in your query; you would have just counted the number of records in APPOINTMENT. When you're naming parameters the same as columns in a table you have to explicitly limit the scope to the parameter in any queries you write, for instance:
select count(nappoint) into num_a
from appointment a
where calc_a.bidoctor = a.bidoctor; -- HERE

looking for db2 text function or method I can do a text contain rather than like

I'm looking for a db2 function that does a text contain search. At present I am running the following query against the data below....
SELECT distinct
s.search_id,
s.search_heading,
s.search_url
FROM repman.search s, repman.search_tags st
WHERE s.search_id = st.search_id
AND ( UPPER(s.search_heading) LIKE (cast('%REPORT%' AS VARGRAPHIC(32)))
OR (UPPER(st.search_tag) LIKE cast('%REPORT%' AS VARGRAPHIC(32)))
)
ORDER BY s.search_heading;
Which returns...
But if I change the search text to %REPORTS% rather than %REPORT% (which I need to do) the like search does not work and I get zero results.
I read a link that used a function named CONTAINS like below but when trying to use the function I get an error.
SELECT distinct
s.search_id,
s.search_heading,
s.search_url
FROM repman.search s, repman.search_tags st
WHERE s.search_id = st.search_id
AND CONTAINS(s.search_heading, 'REPORTS') = 1
Has anynoe got any suggestions? I'm on db2 version DB2/LINUXPPC 9.1.6.
Thanks
In order to look for a pattern in a string, you can use Regular Expressions. They are built-in DB2 with xQuery since DB2 v9. There are also other ways to do that. I wrote an article in my blog (in Spanish that you can translate) about Regular Expressions in DB2.
xmlcast(xmlquery('fn:matches(\$TEXT,''^[A-Za-z 0-9]*$'')')

Django select only rows with duplicate field values

suppose we have a model in django defined as follows:
class Literal:
name = models.CharField(...)
...
Name field is not unique, and thus can have duplicate values. I need to accomplish the following task:
Select all rows from the model that have at least one duplicate value of the name field.
I know how to do it using plain SQL (may be not the best solution):
select * from literal where name IN (
select name from literal group by name having count((name)) > 1
);
So, is it possible to select this using django ORM? Or better SQL solution?
Try:
from django.db.models import Count
Literal.objects.values('name')
.annotate(Count('id'))
.order_by()
.filter(id__count__gt=1)
This is as close as you can get with Django. The problem is that this will return a ValuesQuerySet with only name and count. However, you can then use this to construct a regular QuerySet by feeding it back into another query:
dupes = Literal.objects.values('name')
.annotate(Count('id'))
.order_by()
.filter(id__count__gt=1)
Literal.objects.filter(name__in=[item['name'] for item in dupes])
This was rejected as an edit. So here it is as a better answer
dups = (
Literal.objects.values('name')
.annotate(count=Count('id'))
.values('name')
.order_by()
.filter(count__gt=1)
)
This will return a ValuesQuerySet with all of the duplicate names. However, you can then use this to construct a regular QuerySet by feeding it back into another query. The django ORM is smart enough to combine these into a single query:
Literal.objects.filter(name__in=dups)
The extra call to .values('name') after the annotate call looks a little strange. Without this, the subquery fails. The extra values tricks the ORM into only selecting the name column for the subquery.
try using aggregation
Literal.objects.values('name').annotate(name_count=Count('name')).exclude(name_count=1)
In case you use PostgreSQL, you can do something like this:
from django.contrib.postgres.aggregates import ArrayAgg
from django.db.models import Func, Value
duplicate_ids = (Literal.objects.values('name')
.annotate(ids=ArrayAgg('id'))
.annotate(c=Func('ids', Value(1), function='array_length'))
.filter(c__gt=1)
.annotate(ids=Func('ids', function='unnest'))
.values_list('ids', flat=True))
It results in this rather simple SQL query:
SELECT unnest(ARRAY_AGG("app_literal"."id")) AS "ids"
FROM "app_literal"
GROUP BY "app_literal"."name"
HAVING array_length(ARRAY_AGG("app_literal"."id"), 1) > 1
Ok, so for some reason none of the above worked for, it always returned <MultilingualQuerySet []>. I use the following, much easier to understand but not so elegant solution:
dupes = []
uniques = []
dupes_query = MyModel.objects.values_list('field', flat=True)
for dupe in set(dupes_query):
if not dupe in uniques:
uniques.append(dupe)
else:
dupes.append(dupe)
print(set(dupes))
If you want to result only names list but not objects, you can use the following query
repeated_names = Literal.objects.values('name').annotate(Count('id')).order_by().filter(id__count__gt=1).values_list('name', flat='true')