How to parse nested SQL statement using calcite? - apache-calcite

Select a,b,c from d where d.id in (select id from (select id from e))
Above is the sample query I want to parse using calcite.

String query = "Select a,b,c from d where d.id in (select id from (select id from e))";
try {
SqlParser parser = SqlParser.create(query);
SqlNode sqlNode = parser.parseQuery();
sqlNode.accept(new SqlAnalyzer());
} catch (SqlParseException e) {
e.printStackTrace();
}
With the above code you can use Calcite to parse the SQL query and you will get the parse tree. In order to actually use the tree you need to use the visitor pattern by implementing org.apache.calcite.sql.util.SqlVisitor interface.

Related

I have to convert below SQL Query to informatica cloud logic

Out put of joiner transformation(TestData table name in SQL Query) as below
I need to load data in to target as below
I wrote SQL Query like
SELECT * FROM TestData AS A
WHERE SourceSystem = 'NC' AND
EXISTS
(SELECT * FROM TestData AS B
WHERE B.ClusterID = A.ClusterID AND B.SourceString = '50012559'
AND B.SourceSystem = 'ACB'
)
can you help me how to covert this SQL Query to Informatica cloud .
Assuming testData is a joiner output here is the solution. I assumed, cluster id is the unique key. if it not unique key, then this solution will cause duplicates.
First, sort your joiner output TestData by ClusterID.
Then put a filter(filter1) on SourceSystem = 'NC' and create pipeline 1.
Connect another filter(filter2) to sorter on SourceString = '50012559' AND B.SourceSystem = 'ACB' and create pipeline 2.
Add another joiner - conditions will be pipeline1.ClusterID =pipeline2.ClusterID.
The output from joiner will be your desired data.
This is how the mapping would look like -
|-Filter 1 ->|
TestData_Joiner... -SRT_ClusterID-->|-Filter 2 ->| -JNR_ClusterID-> <desired output>
Pls note, this will generate data just like below SQL.
``
SELECT * FROM TestData AS A WHERE SourceSystem = 'NC' AND EXISTS (SELECT * FROM TestData AS B WHERE B.ClusterID = A.ClusterID AND B.SourceString = '50012559' AND B.SourceSystem = 'ACB' )

How is it possible to map column names from a Doctrine sql query?

I created a query with query builder like this:
$qb = $em->createQueryBuilder();
$qb->select(['u.id', 'u.name'])
->from(User::class, 'u')
->where('u.active = 1')
;
$sql = $qb->getQuery()->getSql();
The result looks like this:
SELECT u1_.user_id as s1, u1_.full_name as s2 FROM users u1_ WHERE u1_.is_active = 1
I would like to execute it as a native query, but I have to find out, how to map s1, s2 to id, name.
you have to use as inside your select
using your example =>
$qb = $em->createQueryBuilder();
$qb->select(['u.id as s1', 'u.name as s2'])
->from(User::class, 'u')
->where('u.active = 1');
$sql = $qb->getQuery()->getSql();
this maps id to s1 and name as s2
Not sure I understand your question but if you want to run a native query with, in the result, the columns id and name, you can replace them in the query, they're aliases so they can be anything you want :
SELECT u.user_id as id, u.full_name as name FROM users u WHERE u.is_active = 1

How to parse SQL Queries and sub queries using sqlparser into python

Want to parse sql join query, select sub query into python. I am using sqlparse library. But i could not parse sub query. How i can parse whole query.
e.g:
query = "select id,fname,lname,address from res_users as r left join res_partner as p on p.id=r.partner_id where name = (select name from res_partner where id = 1)"
query_tokens = sqlparse.parse(query)[0].tokens
I could not parse for this select name from res_partner where id = 1 sub query.
Not so elegant, but works:
import sqlparse
from sqlparse.sql import Where, Comparison, Parenthesis
query = """
select
id,fname,lname,address
from
res_users as r
left join
res_partner as p
on
p.id=r.partner_id
where
name = (select name from res_partner where id = 1)"""
query_tokens = sqlparse.parse(query)[0]
where = next(token for token in query_tokens.tokens if isinstance(token, Where))
condition = next(token for token in where.tokens if isinstance(token, Comparison))
subquery = next(token for token in condition.tokens if isinstance(token, Parenthesis))
print subquery
prints:
(select name from res_partner where id = 1)
This library can parse and generate SQL https://code.google.com/p/python-sql/

Doctrine2 Query Builder Left Join with Select

I want to implement this SQL using doctrine2 query builder:
SELECT c.*, COUNT(s.id) AS studentCount
FROM classes c
LEFT JOIN (
SELECT *
FROM student_classes
WHERE YEAR = '2012'
) sc ON c.id = sc.class_id
LEFT JOIN students s ON sc.student_id = s.id
GROUP BY c.id
I tried this one but didn't work
$qb = $this->getEntityManager()
->getRepository('Classes')
->createQueryBuilder('c');
$qb->select('c.id AS id, c.name AS name, COUNT(s) AS studentCount');
$qb->leftJoin(
$qb->select('sc1')
->from('StudentClasses', 'sc1')
->where('sc1.year = :year')
->setParameter('year', $inputYear),
'sc2'
);
$qb->leftJoin('sc2.students', 's');
$qb->groupBy('c.id');
return $qb->getQuery()->getScalarResult();
or should I use nativeSQL instead?
any help would be appreciated,
thanks.
What are you trying to do is really interesting, because JOIN on a SELECT seems to not be supported by Doctrine2 with DQL or QueryBuilder. Of course, you can try with a native query.
However, to answer to your question, I believe that you don't need to make a JOIN on a SELECT. Simply, JOIN on StudentClasses and then add a condition in the WHERE about the $year! The WHERE clause is made for that.
You can use WITH clause to join entity with additional check, For your subquery you can write the same using left join with year filter, In join part i have used c.studentClasses based on the assumption that in Classes entity you have some mapped property for StudentClasses entity
$qb = $this->getEntityManager()
->getRepository('Classes')
->createQueryBuilder('c');
$qb->select('c.id AS id, c.name AS name, COUNT(s) AS studentCount');
$qb->leftJoin('c.studentClasses','sc2', 'WITH', 'sc2.year = :year');
$qb->leftJoin('sc2.students', 's');
$qb->setParameter('year', $inputYear);
$qb->groupBy('c.id');

Nested statements in sqlite

I'm using the sqlite3 library in c++ to query the database from *.sqlite file. can you write a query statement in sqlite3 like:
char* sql = "select name from table id = (select full_name from second_table where column = 4);"
The second statement should return an id to complete the query statement with first statement.
Yes you can, just make sure that the nested query doesn't return more than one row. Add a LIMIT 1 to the end of the nested query to fix this. Also make sure that it always returns a row, or else the main query will not work.
If you want to match several rows in the nested query, then you can use either IN, like so:
char* sql = "select name from table WHERE id IN (select full_name from second_table where column = 4);"
or you can use JOIN:
char* sql = "select name from table JOIN second_table ON table.id = second_table.full_name WHERE second_table.column = 4"
Note that the IN method can be very slow, and that JOIN can be very fast, if you index on the right columns
On a sidenote, you can use SQLiteadmin (http://sqliteadmin.orbmu2k.de/) to view the database and make queries directly in it (useful for testing etc).