Check array contain at least all value of array - mysql

I got a question about MySQL query.
I have a table role and another table context. Each role could be linked with multiple context using a join table role_context. Example:
roleA->context1
roleA->context2
roleB->context1
I want a query to get all Roles that match all context I give. Example:
If I have ['context1'] in parameter I want ['roleA', 'roleB'] in result.
If I have ['context2'] in parameter I want ['roleA'] in result.
If I have ['context1', 'context2'] in parameter I want ['roleA'] in result.
I have tried to use
SELECT *
FROM role_context
INNER JOIN context ON role_context.context_name = context.name
WHERE context.name IN ["ETT","FR"]
But like it's an in it return roleA and roleB for my third condition.
Does someone have an idea for this query?
Or maybe my SQL architecture is not good?

The architecture is OK, its just that SQL does not have built-in operators for such tasks. You can use the following query to select roles that have all contexts in the given list (must be passed as an IN clause):
SELECT role_context.role_name
FROM role_context
JOIN context ON role_context.context_name = context.name
WHERE context.name IN ('context1', 'context2')
GROUP BY role_context.role_name
HAVING COUNT(context.name) = 2 -- here 2 corresponds to the number of items in the above list

Related

SELECT statement inside a CASE statement in SNOWFLAKE

I have a query where i have "TEST"."TABLE" LEFT JOINED to PUBLIC."SchemaKey". Now in my final select statement i have a case statement where i check if c."Type" = 'FOREIGN' then i want to grab a value from another table but the table name value i am using in that select statement is coming from the left joined table column value. I've tried multiple ways to get to work but i keep getting an error, although if i hard code the table name it seems to work. i need the table name to come from c."FullParentTableName". Is what i am trying to achieve possible in snowflake and is there a way to make this work ? any help would be appreciated !
SELECT
c."ParentColumn",
c."FullParentTableName",
a."new_value",
a."column_name"
CASE WHEN c."Type" = 'FOREIGN' THEN (SELECT "Name" FROM TABLE(c."FullParentTableName") WHERE "Id" = 'SOME_ID') ELSE null END "TestColumn" -- Need assistance on this line...
FROM "TEST"."TABLE" a
LEFT JOIN (
select s."Type", s."ParentSchema", s."ParentTable", s."ParentColumn", concat(s."ParentSchema",'.','"',s."ParentTable",'"') "FullParentTableName",s."ChildSchema", s."ChildTable", trim(s."ChildColumn",'"') "ChildColumn"
from PUBLIC."SchemaKey" as s
where s."Type" = 'FOREIGN'
and s."ChildTable" = 'SOMETABLENAME'
and "ChildSchema" = 'SOMESCHEMANAME'
) c
on a."column_name" = c."ChildColumn"
Thanks !
In Snowflake you cannot dynamically use the partial results as tables.
You can use a single bound value via identifier to bind a value to table name
But you could write a Snowflake Scripting but it would need to explicitly join the N tables. Thus if you N is fixed, you should just join those.

not self explicable 1064 error trying to use MEMBER OF in a mysql query

I have a query where I select some rows of a table based on their ID.
SELECT id,hotel_name FROM hotel WHERE id IN (1,2) and this works fine.
It returns two rows from hotel, id 1 and id 2 as expected. IDs in the where clause are hardcoded but data are coming from another table where they are stored in a json column as ["1","2"]. On a normal table i'd have done I'd have done (WHERE id in (SELECT ...) so I tried to replace the IN operator whith MEMBER OF that should behave like IN for JSON columns.
SELECT id,hotel_name FROM hotel
WHERE id MEMBER OF (
SELECT details FROM auth_events
WHERE auth_events.id_user=1 AND auth_events.id_auth_catalog=10
);
but I get
Syntax error in the query next to 'SELECT details FROM auth_events WHERE auth_events.id_user=1 AND auth_events.id_a'
but I don't understand exactly what is raising it. The inner query SELECT details FROM auth_events WHERE auth_events.id_user=1 AND auth_events.id_auth_catalog=10 is returning correctly the ["1","2"] array.
Can anyone help me understand what am I doing wrong? Also note that my mysql version is 8.0.26 and MEMBER OF is available since 8.0.13 so this shouldn't be the point
The operand of MEMBER OF must be scalar JSON array, not a rowset.
Use
SELECT id,hotel_name
FROM hotel
JOIN auth_events ON auth_events.id_user=1
AND auth_events.id_auth_catalog=10
AND hotel.id MEMBER OF (auth_events.details);
PS. The MEMBER OF() operator was added in MySQL 8.0.17, not in 8.0.13.

Join Tables with sum in sql query

It is showing Sum(with table name) is not valid. Kindly help:
Modws.DisplayDataGrid(dgvClosingBalance,
"Select
Invoice.Customer, Invoice.Sum(Total),
RptTempTable.Sum(INVOICETOTAL), RptTempTable.Sum(CNTOTAL),
RptTempTable.Sum(DEBITTOTAL), RptTempTable.Sum(RECEIPTTOTAL)
From Invoice
inner join RptTempTable on Invoice.Customer = RptTempTable.Customer")
RptTempTable.Sum(INVOICETOTAL) should be Sum(RptTempTable.INVOICETOTAL)
The same goes for the other calls to sum()
The table prefix belongs to the column name not the function call.
MySQL will accept this invalid SQL and will return "inderminate" (aka "random") values instead.
To understand the implications of MySQL's "loose" (aka "sloppy") group by implementation you might want to read these articles:
http://www.mysqlperformanceblog.com/2006/09/06/wrong-group-by-makes-your-queries-fragile/
http://rpbouman.blogspot.de/2007/05/debunking-group-by-myths.html

Using Django Count() with conditional lookup types

So I'm trying to aggregate exam data, and because the database lives on another server I'm trying to reduce this to as few database calls as possible.
I have this model (whose corresponding table is in a mySQL database if that matters):
class Exam(models.Model):
submitted = models.BooleanField(default=False)
score = models.DecimalField(default=Decimal(0))
And this query:
>>> exam_models.Exam.objects\
... .using("exam_datebase")\
... .aggregate(average=Avg("score"),
... total=Count("submitted"))
{'average': 22.251082, 'total': 231}
What I'm looking for is a way to also retrieve the number of passed exams, something along the lines of:
>>> exam_models.Exam.objects\
... .using("exam_datebase")\
... .aggregate(average=Avg("score"),
... total=Count("submitted"))
... passed=Count("score__gte=80"))
{'average': 22.251082, 'total': 231, 'passed': 42}
I know I can just send another query using .filter(score__gte=80).count(), but I was really hoping to get both the total count and the passing count on the same aggregate. Any ideas?
You are either going to need two queries, or do the aggregation manually.
To see why, let's consider the underlying SQL that Django generates and uses to query the database.
Exam.objects.aggregate(average=Avg("score"), total=Count("submitted"))
roughly translates to
SELECT AVG(score), COUNT(submitted)
FROM exam
The "Count" part of the aggregate is applying to the SELECT clause in the underlying sql query. But if we want to include only scores greater than some value, the SQL query would need to look something like this:
SELECT AVG(score), COUNT(submitted)
FROM exam
WHERE score > 80
Filtering Exams with a particular "score" is applies to the WHERE or HAVING clause of the underlying SQL statement.
Unfortunately, there is not really a way to combine these two things. So, you are stuck doing two queries.
Having said all that, if you REALLY want to do a single query, one option is to just do the aggregation in your python code:
exams = Exam.objects.all()
total_score = 0
total_submitted = 0
passed = 0
for exam in exams:
total_score += exam.score
if exam.submitted:
total_submitted += 1
if exam.score >= 80:
passed += 1
exam_aggregates = {
'average': total_score / len(exams),
'submitted': total_submitted,
'passed': passed,
}

mysql view super slow

this is the query for Unified Medical Language System(UMLS) to find a word related to normalized word. this query result is 165MS, but if I am running VIEW of this same query it is taking 70 sec. I m new to the mysql. Please help me.
Query:
SELECT a.nwd as Normalized_Word,
b.str as String,
c.def as Defination,
d.sty as Semantic_type
FROM mrxnw_eng a, mrconso b, mrdef c, mrsty d
WHERE a.nwd = 'cold'
AND b.sab = 'Msh'
AND a.cui = b.cui
AND a.cui = c.cui
AND a.cui = d.cui
AND a.lui = b.lui
AND b.sui = a.sui
group by a.cui
View definition:
create view nString_Sementic as
SELECT a.nwd as Normalized_Word,
b.str as String,
c.def as Defination,
d.sty as Semantic_type
FROM mrxnw_eng a, mrconso b, mrdef c, mrsty d
WHERE b.sab = 'Msh'
AND a.cui = b.cui
AND a.cui = c.cui
AND a.cui = d.cui
AND a.lui = b.lui
AND b.sui = a.sui
group by a.cui
Selection from view:
select * nString_Sementic
where nwd = 'phobia'
You may be able to get better performance by specifying the VIEW ALGORITHM as MERGE. With MERGE MySQL will combine the view with your outside SELECT's WHERE statement, and then come up with an optimized execution plan.
To do this however you would have to remove the GROUP BY statement from your VIEW. As it is, a temporary table is being created of the entire view first, before being filtered by your WHERE statement.
If the MERGE algorithm cannot be used, a temporary table must be used
instead. MERGE cannot be used if the view contains any of the
following constructs:
Aggregate functions (SUM(), MIN(), MAX(), COUNT(), and so forth)
DISTINCT
GROUP BY
HAVING
LIMIT
UNION or UNION ALL
Subquery in the select list
Refers only to literal values (in this case, there is no underlying
table)
Here is the link with more info. http://dev.mysql.com/doc/refman/8.0/en/view-algorithms.html
If you can change your view to not include the GROUP BY statement, to specify the view's algorithm the syntax is:
CREATE ALGORITHM = MERGE VIEW...
Edit: This answer was originally based on MySQL 5.0. I've updated the links to point to the current documentation, but I have not otherwise confirmed if the answer correct for versions >5.0.
Assuming that mrxnw_eng.nwd is functionally dependent on mrxnw_eng.cui, try changing the group by clause of the view to include a.nwd - like so:
group by a.cui, a.nwd