I have a hierarchical data structure as following Where nodes are mapped to the parent node as following:
#Entity
public class Node implements Serializable {
#Id
private long id;
#Column(name="PARENT_ID")
private Long parentId;
#OneToMany
#JoinColumn(name="PARENT_ID")
public List<Node> children = new LinkedList<Node>();
}
So for example lets say I have the following data:
[A]
/ \
/ \
/ \
[B] [C]
/ \ \
/ \ \
[D] [E] [F]
\
\
[G]
Now I want to build a dynamic query in JPA CriteriaBuilder that can query for any node and return the results of its children as well. For example if I query for B, I get the following results:
B
D
E
G
And, if I query for E, I get:
-E
-G
And so on...
Since I'm using SQL Server 2012 as my database I have used with clause as following:
Assuming [E] node id is 8:
Top to Bottom:
WITH NODE_TREE AS(
SELECT N.ID, N.PARENT_ID FROM NODE_TABLE N WHERE N.ID = 8
UNION ALL
SELECT N.ID, N.PARENT_ID FROM NODE_TABLE N
INNER JOIN NODE_TREE NT
ON N.ID = NT.PARENT_ID
)
SELECT * FROM NODE_TREE;
This will return a top-to-bottom list of nodes:
B, E, D, G
Bottom to Top:
WITH NODE_TREE AS(
SELECT N.ID, N.PARENT_ID FROM NODE_TABLE N WHERE N.ID = 8
UNION ALL
SELECT N.ID, N.PARENT_ID FROM NODE_TABLE N
INNER JOIN NODE_TREE NT
ON N.PARENT_ID = NT.ID
)
SELECT * FROM NODE_TREE;
This will return a bottom-to-top list of nodes:
B, A
Related
SELECT x, createddate, count_ FROM
(SELECT *, count(*)
OVER
(PARTITION BY
x
) AS count_
FROM machineslocation_loc AS ml
JOIN m AS ma ON ma.mid= ml.mid
JOIN sh AS sh ON sh.shid = ma.shid
JOIN ph AS ph ON ph.phid = sh.phid
JOIN ar AS ar ON ar.arid = ph.arid
JOIN pn AS pa ON pa.pnid = ar.pnid
AND x LIKE '%705N%') tableWithCount
The table machineslocation_loc has createddate column in it. Whenever I call it says "missing FROM-clause entry for table "machineslocation_loc" but x column is coming from that table. I tried ml.createddate and machineslocation_loc.createddate. There are createddate column in other tables too
Try calling using the alias of your subquery, and please avoid * , call the name by his name
SELECT x, tableWithCount.createddate, count_ FROM
(SELECT x, ml.*,ma.*,sh.*,ph.*,ar.*,pa.*, count(*)
OVER
(PARTITION BY
x
) AS count_
FROM machineslocation_loc AS ml
JOIN m AS ma ON ma.mid= ml.mid
JOIN sh AS sh ON sh.shid = ma.shid
JOIN ph AS ph ON ph.phid = sh.phid
JOIN ar AS ar ON ar.arid = ph.arid
JOIN pn AS pa ON pa.pnid = ar.pnid
AND x LIKE '%705N%') as tableWithCount
make sure that not exist another column named createddate from the other tables inside the subquery
UPDATE:but you do not use the rest of the columns on the main query, so remove the * and only put the columns that you need, for example:
SELECT x, tableWithCount.mlcreateddate, count_ FROM
(SELECT x,ml.createddate mlcreateddate, count(*)
OVER
(PARTITION BY
x
) AS count_
FROM machineslocation_loc AS ml
JOIN m AS ma ON ma.mid= ml.mid
JOIN sh AS sh ON sh.shid = ma.shid
JOIN ph AS ph ON ph.phid = sh.phid
JOIN ar AS ar ON ar.arid = ph.arid
JOIN pn AS pa ON pa.pnid = ar.pnid
AND x LIKE '%705N%') as tableWithCount
I have the following query in Postgres:
SELECT *
from table1
LEFT OUTER JOIN table1.table2 ON table1.latest_id = table2.id
WHERE table1.table2.status = 0
AND table1.id NOT IN (
(SELECT id from table3 where userId = table2.user))
I do not have the ability to join table1 and table3 and I am stuck writing the subquery in a format JPA will understand - working with a spring boot app. Here is where I got so far in my repository class:
#Query("SELECT c FROM #{#entityName} c JOIN FETCH c.table2 WHERE c.table2.status = 0")
fun findByIdAndStatus(id: String): MyEntity
I have attempted at the subquery as follows, but with no joy - there is a clear syntax error I cannot wrap my head around:
#Query("SELECT c FROM #{#entityName} c JOIN FETCH c.table2 WHERE c.table2.status = 0" AND c.id NOT IN (" +
"SELECT * FROM Table3 WHERE userId = c.table2.user")
Can you help?
Thank you
Assuming:
your SQL query doesn't utilize any input arguments
table1 is mapped by MyEntity and table3 is mapped by Table3 entity
entity associated with table2 is mapped in MyEntity using latest_id join column
status is mapped as a number (i.e Long / Integer)
You can rewrite the query to following JPQL form:
#Query("SELECT t1 FROM MyEntity t1 "
+ "JOIN t1.table2 t2 "
+ "WHERE t2.status = 0 AND t1.id NOT IN ("
+ " SELECT t3.id from Table3 t3 "
+ " WHERE t3.userId = t2.user "
+ ")")
List<MyEntity> findMyEntities();
I am creating SQL query that involves multiple tables with 1 to N relation to support pagination.
To get the first 10 parents, I tried to do
SELECT * from parent p
LEFT JOIN child c
ON c.parent_id = p.id
LIMIT 10
This does not work if any parent has more than one children
One alternative I can do is
SELECT * from parent LIMIT 10 into temp_p;
SELECT * from temp_p p
LEFT JOIN child c
ON c.parent_id = p.id
This is pretty clumsy. What I would like to do is
SELECT * from parent p LIMIT 10
LEFT JOIN child c
ON c.parent_id = p.id
but of course the syntax is wrong. I am wondering if Postgresql have some way to support what I want to do.
Use a common table expression:
WITH ten_parents AS (
SELECT * from parent LIMIT 10)
SELECT *
FROM ten_parents p
LEFT JOIN child c
ON c.parent_id = p.id
I have a following script to get the total unit but it gives me an error
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
Do I need to calculate SUM(ta.Qty) outside the main table?
SELECT
ta.ProductName
, SUM(ta.Total)
, SUM(SUM(ta.Qty) * ta.Unit)
FROM
tableA tA
INNER JOIN
tableB tB on tA.ID = tb.TableAID
INNER JOIN
tableC tc on ta.ID = tc.TableAID
INNER JOIN
tableD td on td.ID = tb.TableBID
GROUP BY
ta.ProductName
Here is a query in the AdventureWorks database that produces the same error (but might make some sense):
SELECT v.Name AS Vendor, SUM(SUM(p.ListPrice*d.OrderQty)+h.Freight)
FROM Production.Product p
INNER JOIN Purchasing.PurchaseOrderDetail d ON p.ProductID = d.ProductID
INNER JOIN Purchasing.PurchaseOrderHeader h ON h.PurchaseOrderID = d.PurchaseOrderID
INNER JOIN Purchasing.Vendor v ON v.BusinessEntityID = h.VendorID
GROUP BY v.Name
And here are two ways that I could rewrite that query to avoid the error:
SELECT v.Name AS Vendor, SUM(x.TotalAmount+h.Freight)
FROM (
SELECT PurchaseOrderID, SUM(p.ListPrice*d.OrderQty) AS TotalAmount
FROM Production.Product p
INNER JOIN Purchasing.PurchaseOrderDetail d ON p.ProductID = d.ProductID
GROUP BY PurchaseOrderID
) x
INNER JOIN Purchasing.PurchaseOrderHeader h ON h.PurchaseOrderID = x.PurchaseOrderID
INNER JOIN Purchasing.Vendor v ON v.BusinessEntityID = h.VendorID
GROUP BY v.Name
SELECT v.Name AS Vendor, SUM(x.TotalAmount+h.Freight)
FROM Purchasing.PurchaseOrderHeader h
INNER JOIN Purchasing.Vendor v ON v.BusinessEntityID = h.VendorID
CROSS APPLY (
SELECT SUM(p.ListPrice*d.OrderQty) AS TotalAmount
FROM Production.Product p
INNER JOIN Purchasing.PurchaseOrderDetail d ON p.ProductID = d.ProductID
WHERE d.PurchaseOrderID=h.PurchaseOrderID
) x
GROUP BY v.Name
The first query uses derived tables and the second one uses CROSS APPLY.
I have a SQL Server table. Now this table has columns like primary key Id, A, B, C, D, E, F, G
Now I want to select rows from this table like this
A=A, B=B, C=C, D=D and G > 132
So I am trying to select rows from this table which rows A,B,C,D columns has same data and G column data > 132.
So how can I do that ? Thank you.
I tried this query but returning same Id rows
SELECT TableA.Id,TableA.UserId,TableA.MaximumHp,TableA.Attack,TableA.Defense,TableA.SpAttack,TableA.SpDefense,TableA.Speed
FROM myTable as TableA
Inner Join myTable as TableB on
TableA.MaximumHp = TableB.MaximumHp
AND TableA.Attack = TableB.Attack
AND TableA.Defense = TableB.Defense
AND TableA.SpAttack = TableB.SpAttack
AND TableA.SpDefense = TableB.SpDefense
AND TableA.Speed = TableB.Speed
AND TableA.Id != TableB.Id
SQL Server 2008 R2
Sounds like you want to join the table to itself
SELECT *
FROM Table t1
Inner Join Table t2 on t1.A = t2.A
AND t1.B = t2.B
AND t1.C = t2.C
AND t1.D = t2.D
AND t1.G > 132
AND t1.ID <> t2.ID
I THINK what you mean is duplicates. Tell me if this is what you are looking for.
SELECT [Table].A, [Table].B, [Table].C, [Table].D, [Table].E, [Table].F, [Table].G
FROM [Table] LEFT JOIN (SELECT A, B, C, D FROM [Table]
GROUP BY A, B, C, D
HAVING count(*) > 1)
AS sub ON ([Table].A=sub.A) AND ([Table].B=sub.B) AND ([Table].C=sub.C) AND ([Table].D=sub.D)
WHERE G>132 and sub.A is not null;
This will give you all the rows where a,b,c, and D are equal to another row in the table...and G > 132