SQL or django query to find the similar entries - sql

I want to return the user a list of similar tasks. Two tasks A and B are considered similar if all the words in task A exist in task B or vice versa.
I tried the query given below but couldn't get the required result.
SELECT t1.task
FROM todolistapp_todo t1
LEFT JOIN todolistapp_todo t2
ON
t1.task in (t2.task) and t1.id != t2.id;
I'm able to do this by the nested loop. But I want to do it with minimum complexity.
similar = set()
for task in tasks:
for nested_task in tasks
if (task.task in nested_task.task or nested_task.task in task.task) and task.id != nested_task.id:
similar.add(task)

can you try:
[similar.add(similar_task) for similar_task in tasks if tasks.filter(task=similar_task.task).count()>1]
I'm on phone then sorry if not working :)

Related

How to join 2 tables with multiple conditions each?

I have data split between 2 tables, and need to join the necessary data together for analysis.
One table Test 3 Output contains ID numbers, and the return value of the test. The other table Test Results contains the same IDs, along with their corresponding serial number and overall test result.
I need to combine these into a single table that just displays ID, serial number and test value.
Sorry in advance for the horrible SQL thats about to follow, I'm brand new to this.
I have 2 working queries that give me what I want, but I can't seem to join them together.
The first query:
select `ID`,`Serial Number` from `Test Results`t where (len(`Serial Number`)=16 and FailMode = '24V Supply FAIL')
This gets me the ID and serial number of all the tests that failed '24V supply'. It also filters out garbage serial numbers as the correct ones should have 16 digits.
The second query:
select `ID` from `Test 3 Output`o where o.`24V Supply (V)`<30
This gets me the ID and test results, and filters out some results that were greater than 30V. Note that '24V Supply(V) is the name of the column containing the test results.
Now when I try to join these with the ID, I get a syntax error. Here's what I tried:
select `ID`,`Serial Number`
from `Test Results`t
where (len(`Serial Number`)=16 and FailMode = '24V Supply FAIL')
left join (`Test 3 Output`o ON t.`ID` = o.`ID` where o.`24V Supply (V)`<30)
This gives the error:
Error: Syntax error (missing operator) in query expression (len(`Serial Number`)=16 and FailMode = '24V Supply FAIL') left join (`Test 3 Output`o ON t.`ID` = o.`ID` where o.`24V Supply (V)`<30)
I'm not sure what operator I'm missing but I had a feeling its related to the fact there's two where statements?
Can anyone offer some help?
Edit: I found a workaround since I can't use 2 where clauses with a join. I created 2 views with my 2 separate queries, and performed the join on those which got me what I wanted. I'd still like to hear a proper way of doing it though :)
You can join 2 subqueries like this:
SELECT q1.a, q1.b, q2.c
FROM (
(SELECT a, b FROM table1
WHERE b > 10) AS q1
LEFT JOIN
(SELECT a, c FROM table2
WHERE c > 20) AS q2
ON q1.a = q2.a
)
Doing the subqueries as separate query objects is easier to debug, but the query objects keep piling up...

How to find all pair of polygons which only touch each other in a point and only list each pair once

How to find all pair of polygons which only touch each other in a point and only list each pair once in PostgreSQL using PostGIS?
like the cycle shown on the picture:
I have written the following query:
with kms as (
select
a.county as cn1,
b.county as cn2
from spatial.us_counties as a, spatial.us_counties as b
where ST_Touches(a.geom, b.geom) = 'true' and a.id != b.id and ST_GeometryType(ST_Intersection(a.geom,b.geom)) = 'ST_Point'
)
/** below is for remove reversed pairs **/
SELECT t1.cn1
,t1.cn2
FROM kms AS t1
LEFT OUTER JOIN kms AS t2
ON t1.cn1 = t2.cn2
AND t1.cn2 = t2.cn1
WHERE t2.cn1 IS NULL
OR t1.cn1 < t2.cn1
But this query caused serious performance issue and it returned all pairs twice (reversed pair)
This approach is not the solution at all.
So is there anyone can help me with that or give me any hints?
I'm not absolutely sure so I need your feedback for this answer..
Try:
SELECT DISTINCT A.county
FROM spatial.us_counties AS A, spatial.us_counties AS B
WHERE ST_Touches(A.geom, B.geom) = 'true'
According to: https://postgis.net/docs/ST_Touches.html ST_Touches should return touching polygons only and not intersecting so this should eliminate the need for the where statement that checks if it's a point intersection. Selecting DISTINCT should help with the duplicates.
Adding an index https://postgis.net/docs/using_postgis_dbmanagement.html#idm2269 to the table will help speed up the geometry queries. Let me know if you've already done all this, I can edit my answer.

Grails Self Referencing Criteria

In the project I´m working there is a part of the database that is like the following diagram
The domain classes have a definition similar to the following:
class File{
String name
}
class Document{
File file
}
class LogEntry{
Document document
Date date
}
First I need to get only the latest LogEntry for all Documents; in SQL I do the following (SQL_1):
SELECT t1.* FROM log_entry AS t1
LEFT OUTER JOIN log_entry t2
on t1.document_id = t2.document_id AND t1.date < t2.date
WHERE t2.date IS NULL
Then in my service I have a function like this:
List<LogEntry> logs(){
LogEntry.withSession {Session session ->
def query = session.createSQLQuery(
"""SELECT t1.* FROM log_entry AS t1
LEFT OUTER JOIN log_entry t2
on t1.document_id = t2.document_id AND t1.date < t2.date
WHERE t2.date IS NULL"""
)
def results = query.with {
addEntity(LogEntry)
list()
}
return results
}
}
The SQL query does solve my problem, at least in a way. I need to also paginate, filter and sort my results as well as join the tables LogEntry, Document and File. Altough it is doable in SQL it might get complicated quite quickly.
In other project I´ve used criteriaQuery similar to the following:
Criteria criteria = LogEntry.createCriteria()
criteria.list(params){ //Max, Offset, Sort, Order
fetchMode 'document', FetchMode.JOIN //THE JOIN PART
fetchMode 'document.file', FetchMode.JOIN //THE JOIN PART
createAlias("document","_document") //Alias could be an option but I would need to add transients, since it seems to need an association path, and even then I am not so sure
if(params.filter){ //Filters
if(params.filter.name){
eq('name', filter.name)
}
}
}
In these kinds of criteria I´ve been able to add custom filters, etc. But I have no Idea how to translate my query(SQL_1) into a criteria. Is there a way to accomplish this with criteriaBuilders or should I stick to sql?

Improved way for multi-table SQL (MySQL) query?

Hoping you can help. I have three tables and would like to create a conditional query to make a subset based on a row's presence in one table then excluding the row from the results, then query a final, 3rd table. I thought this would be simple enough, but I'm not well practiced in SQL and after researching/testing for 6 hours on left joins, correlated sub-queries etc, it has helped, but I still can't hit the correct result set. So here's the setup:
T1
arn_mkt_stn
A00001_177_JOHN_FM
A00001_177_BILL_FM
A00001_174_DAVE_FM
A00002_177_JOHN_FM
A00006_177_BILL_FM
A00010_177_JOHN_FM - note: the name's relationship to the 3 digit prefix (e.g. _177) and the FM part always is consistent: '_177_JOHN_FM' only the A000XX changes
T2
arn_mkt
A00001_105
A00001_177
A00001_188
A00001_246
A00002_177
A00003_177
A00004_026
A00004_135
A00004_177
A00006_177
A00010_177
Example: So if _177_JOHN_FM is a substring of arn_mkt_stn rows in T1, exclude it when getting arn_mkts with a substring of 177 from T2 - in this case, the desired result set would be:
A00003_177
A00004_177
A00006_177
Similarly, _177_BILL_FM would return:
A00002_177
A00003_177
A00004_177
A00010_177
Then I would like to use this result set to pull records from a third table based on the 'A00003' etc
T3
arn
A00001
A00002
A00003
A00004
A00005
A00006
...
I've tried a number of methods [where here $stn_code = JOHN_FM and $stn_mkt = 177]
"SELECT * FROM T2, T1 WHERE arn != SUBSTRING(T1.arn_mkt_stn, 1,6)
AND SUBSTRING(T1.arn_mkt_stn, 12,7) = '$stn_code'
AND SUBSTRING(arn_mkt, 8,3) = '$stn_mkt' (then use this result to query T3..)
Also a left join and a subquery, but I'm clearly missing something!
Any pointers gratefully received, thanks,
Rich.
[EDIT: Thanks for helping out sgeddes. I'll expand on my logic above... first, the result set desired is always in connection with one name only per query, e.g. from T1, lets use JOHN_FM. In T1, JOHN_FM is currently associated with 'arn's (within the arn_mkt_stn): A00001, A00002 & A00010'. The next step in T2 is to find all the 'arn's (within arn_mkt)' that have JOHN_FM's 3 digit prefix (177), then exclude those that are in T1. Note: A00006 remains because it is not connected to JOHN_FM in T1. The same query for BILL_FM gives slightly different results, excluding A00001 & A00006 as it has this assoc in T1.. Thanks, R]
You can use a LEFT JOIN to remove the records from T2 that match those in T1. However, I'm not sure I'm understanding your logic.
You say A00001_177_JOHN_FM should return:
A00003_177
A00004_177
A00006_177
However, wouldn't A00006_177_BILL_FM exclude A00006_177 from the above results?
This query should be close (wasn't completely sure which fields you needed returned) to what you're looking for if I'm understanding you correctly:
SELECT T2.arn_mkt, T3.arn
FROM T2
LEFT JOIN T1 ON
T1.arn_mkt_stn LIKE CONCAT(T2.arn_mkt,'%')
INNER JOIN T3 ON
T2.arn_mkt LIKE CONCAT(T3.arn,'%')
WHERE T1.arn_mkt_stn IS NULL
Sample Fiddle Demo
--EDIT--
Reviewing the comments, this should be what you're looking for:
SELECT *
FROM T2
LEFT JOIN T1 ON
T1.arn_mkt_stn LIKE CONCAT(LEFT(T2.arn_mkt,LOCATE('_',T2.arn_mkt)),'%') AND T1.arn_mkt_stn LIKE '%JOHN_FM'
INNER JOIN T3 ON
T2.arn_mkt LIKE CONCAT(T3.arn,'%')
WHERE T1.arn_mkt_stn IS NULL
And here is the updated Fiddle: http://sqlfiddle.com/#!2/3c293/13

SQL to query drupal nodes with multiple taxonomies

Good morning all.
I've read some of the suggested question before posting this but seems like no one has my same issue (probably and inidicator of how bad I am in Drupal and coding in general)
I need to write a query that returns all the nodes with TWO SPECIFIC taxonomies associated to it (of which I know the IDs), but it seems I don't know the right syntax cause I just manage to get it work with ONE term id.
Here's what I have so far (and works)
SELECT * FROM node
INNER JOIN term_node AS tn ON node.vid = tn.vid
LEFT JOIN content_type_extra_content AS xc ON node.vid = xc.vid
WHERE tn.tid IN (SELECT th.tid FROM term_hierarchy AS th WHERE th.tid = '146')
That '146' is the id of the first taxonomy term I need to check (call it "shoes")
Now I have to check that the node has also the taxonomy id '223' (call it "season")
I've tried different solutions with no avail.
I'm pretty sure the solution is under my nose but at the moment I can't wrap my head around it.
Please note that the taxonomies are in different vocaboularies and they are at level-0
Thanks in advance for any help
If I understand you correctly, you want the nodes which have 2 specific terms (shoes and season), then try something like this:
SELECT * FROM node
INNER JOIN term_node AS tn ON node.vid = tn.vid
LEFT JOIN content_type_extra_content AS xc ON node.vid = xc.vid
WHERE tn.tid IN ('146','223')
GROUP BY node.vid
HAVING count(*) = 2