Reputation: 23
I have the following tables (similar to Northwind sample database):
Employee->OrdersWithDetails<-Products tables
Employee(includes employee-manager relationship with 4 levels)
Employee->EmployeeLvls - links employee's level with specific attributes tied to his level
OrdersWithDetails combines Orders & OrderDetails into one set.
For each employee, I’m trying to display employee's orders and $$; i.e. OrderId, SoldAmt and employee’s managers UP the line.
There should be a SINGLE line for the combination of employee and OrderId, but so far I was only able to display multiple lines; for each level -additional line with manager's name is added.
Here is my cypher *
MATCH (e:Employees)-[:JOB_LEVEL_OF]->(el:EmployeeLvls)
where e.Name ="Vidur Luthra" //limiting to a single employee
MATCH (p:Products)-[:PRODUCT]->(owd:OrdersWithDetails)<-[:SOLD]-(e)-[:REPORTS_TO*0..4]->(m:Employees)-[:JOB_LEVEL_OF]->(el_m:EmployeeLvls)
WHERE m.EmployeeId <> e.EmployeeId //excluding employee
RETURN e.Name as Employee ,owd.OrderId
,SUM(owd.ProductQuantity*p.UnitPrice) as SoldAmt //display manager's names based on their level:
,(CASE WHEN m.EmployeeLvlId = e.EmployeeLvlId - 1 THEN m.Name ELSE '-' END) as Manager_1_LevelAbove
,(CASE WHEN m.EmployeeLvlId = e.EmployeeLvlId - 2 THEN m.Name ELSE '-' END) as Manager_2_LevelsAbove
,(CASE WHEN m.EmployeeLvlId = e.EmployeeLvlId - 3 THEN m.Name ELSE '-' END) as Manager_3_LevelsAbove
*
Here is my outcome: current result or
Employee|OrderId|SoldAmt |Manager_1_LevelAbove|Manager_2_LevelsAbove| Manager_3_LevelsAbove
Vidur Luthra|94 |733.49 |James Kramer | |
Vidur Luthra|94 |733.49 | | | Ken Sanchez
Vidur Luthra|94 |733.49 | |Jossef Goldberg |
Here is my desired outcome: desired result or
Employee|OrderId|SoldAmt |Manager_1_LevelAbove|Manager_2_LevelsAbove| Manager_3_LevelsAbove
Vidur Luthra|94 |733.49 |James Kramer |Jossef Goldberg | Ken Sanchez
What should I do?
Upvotes: 2
Views: 651
Reputation: 10856
Another answer to address your comment:
MATCH
(e:Employees)-[:JOB_LEVEL_OF]->(el:EmployeeLvls)
WHERE e.Name ="Vidur Luthra" //limiting to a single employee
MATCH
(p:Products)-[:PRODUCT]->(owd:OrdersWithDetails)<-[:SOLD]-(e),
reporting_path=(e)-[:REPORTS_TO*0..4]->(m:Employees)
WHERE
NOT((m)-[:REPORTS_TO]->()) AND
m.EmployeeId <> e.EmployeeId //excluding employee
WITH e, owd, p, nodes(reporting_path) AS managers
UNWIND managers AS manager
MATCH (manager)-[:JOB_LEVEL_OF]->(el_m:EmployeeLvls)
WITH e, owd, p, collect({Name: manager.Name, JobTitle: el_m.JobTitle}) AS managers
RETURN
e.Name as Employee,
owd.OrderId,
SUM(owd.ProductQuantity * p.UnitPrice) as SoldAmt,
(managers[0]).Name AS Manager_1_LevelAbove,
(managers[0]).JobTitle AS Manager_1_JobTitle,
(managers[1]).Name AS Manager_2_LevelAbove,
(managers[1]).JobTitle AS Manager_2_JobTitle,
(managers[2]).Name AS Manager_3_LevelAbove
(managers[2]).JobTitle AS Manager_3_JobTitle
Upvotes: 0
Reputation: 10856
I think that the best way to do this would be to define a variable for the part of the path that you care about and then use that path:
MATCH
(e:Employees)-[:JOB_LEVEL_OF]->(el:EmployeeLvls)
WHERE e.Name ="Vidur Luthra" //limiting to a single employee
MATCH
(p:Products)-[:PRODUCT]->(owd:OrdersWithDetails)<-[:SOLD]-(e),
reporting_path=(e)-[:REPORTS_TO*0..4]->(m:Employees)
(m)-[:JOB_LEVEL_OF]->(el_m:EmployeeLvls)
WHERE
NOT((m)-[:REPORTS_TO]->()) AND
m.EmployeeId <> e.EmployeeId //excluding employee
RETURN
e.Name as Employee,
owd.OrderId,
SUM(owd.ProductQuantity * p.UnitPrice) as SoldAmt,
(nodes(reporting_path)[0]).Name AS Manager_1_LevelAbove,
(nodes(reporting_path)[1]).Name AS Manager_2_LevelAbove,
(nodes(reporting_path)[2]).Name AS Manager_3_LevelAbove
Note here that I put in a WHERE
clause for NOT((m)-[:REPORTS_TO]->())
. This means that if Jim reports to Sally who reports to Bill and Bill reports to nobody, we're only going to MATCH
on the path between Jim and Bill, not the one between Jim and Sally. That way we don't get duplicates like you're seeing.
Upvotes: 1