Transpose or Pivot - neo4j collect() - neo4j

how to transpose a n x m collection in the return statement ? OR before return statement based on a particular column?
example:
A | B | C
aa | 2 | 3
bb | 4 | 6
cc | 5 | 8
dd | 55| 9
To
aa | bb | cc | dd
2 | 4 | 5 | 55
3 | 6 | 8 | 9
Example:
with [{Label:'User',Lang:'English'},{Label:'Usuario',Lang:'Español'},{Label:'用户',Lang:'中文_简体'}] as t unwind t as p return
this returns
p.Label | p.Lang
User | English
Usuario | Español
用户 | 中文_简体
should be transposed to
User | Usuario | 用户
English | Español | 中文_简体

Well, MAYBE there is what you want in APOC.
CALL apoc.help(KEYWORD)
If not, you are good to write your own function
https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_user_defined_functions

Would extract help? This might get you part-way there:
neo4j> with [{Label:'User',Lang:'English'},{Label:'Usuario',Lang:'Español'},{Label:'用户',Lang:'中文_简体'}] as t return extract( i in t | i.Label), extract(i in t | i.Lang);
+--------------------------------------------------------------+
| extract( i in t | i.Label) | extract(i in t | i.Lang) |
+--------------------------------------------------------------+
| ["User", "Usuario", "用户"] | ["English", "Español", "中文_简体"] |
+--------------------------------------------------------------+

Related

Cypher query aggregate sum of values

I have a Cypher query that shows the following output:
+----------------
| usid | count |
+----------------
| "000" | 1 |
| "000" | 0 |
| "000" | 0 |
| "001" | 1 |
| "001" | 1 |
| "001" | 0 |
| "002" | 2 |
| "002" | 2 |
| "002" | 0 |
| "003" | 4 |
| "003" | 2 |
| "003" | 2 |
| "004" | 4 |
| "004" | 4 |
| "004" | 4 |
+----------------
How can I get the below result with the condition SUM(count) <= 9.
+----------------
| usid | count |
+----------------
| "000" | 1 |
| "001" | 2 |
| "002" | 4 |
| "003" | 8 |
+----------------
Note: I have used the below query to get the 1st table data.
MATCH (us:USER)
WITH us
WHERE us.count <= 4
RETURN us.id as usid, us.count as count;
I don't know how you get your original data, so I will just use a WITH clause and assume the data is there:
// original data
WITH usid, count
// aggregate and filter
WITH usid, sum(count) as new_count
WHERE new_count <= 9
RETURN usid, new_count
Based on the updated question, the new query would look like:
MATCH (us:USER)
WHERE us.count <= 4
WITH us.id as usid, sum(us.count) as count
WHERE new_count <= 9
RETURN usid, count
˙˙˙

Compare each cell in two rows, but with an exception

I have a table that keeps track of scores from a test. It compares the row with someone's answers to the row with the correct data:
A B C D E
+--------------+-----+-----+-----+-------+
1 | | Q1 | Q2 | Q3 | Score |
+--------------+-----+-----+-----+-------+
2 | Answers | C | B | A | |
+--------------+-----+-----+-----+-------+
3 | George | C | A | B | 1 |
4 | Judith | C | C | A | 2 |
5 | James | A | B | C | 1 |
+--------------+-----+-----+-----+-------+
The formula behind the Score column is:
=arrayformula(sumproduct(($B$2:$D$2=B3:D3)))
The first part of sumproduct is a static reference to the Answers row. The second part is comparing it against the row it's on. However I want to add an exception: if the Answers row contains an asterisk it should consider all answers correct:
A B C D E
+--------------+-----+-----+-----+-------+
1 | | Q1 | Q2 | Q3 | Score |
+--------------+-----+-----+-----+-------+
2 | Answers | C | * | A | |
+--------------+-----+-----+-----+-------+
3 | George | C | A | B | 2 |
4 | Judith | C | C | A | 3 |
5 | James | A | B | C | 1 |
+--------------+-----+-----+-----+-------+
How would I be able to do this?
Please try:
=arrayformula(sumproduct(($B$2:$D$2=B3:D3)+($B$2:$D$2="*")))
=IF(OR($B$2=B3, $B$2="*"), 1, )+
IF(OR($C$2=C3, $C$2="*"), 1, )+
IF(OR($D$2=D3, $D$2="*"), 1, )
this will cover up to 51 questions (columns / range of B:AZ)
=IF(LEN($B$2),IF(OR($B$2=B3,$B$2="*"),1,),)+
IF(LEN($C$2),IF(OR($C$2=C3,$C$2="*"),1,),)+
IF(LEN($D$2),IF(OR($D$2=D3,$D$2="*"),1,),)+
IF(LEN($E$2),IF(OR($E$2=E3,$E$2="*"),1,),)+
IF(LEN($F$2),IF(OR($F$2=F3,$F$2="*"),1,),)+
IF(LEN($G$2),IF(OR($G$2=G3,$G$2="*"),1,),)+
IF(LEN($H$2),IF(OR($H$2=H3,$H$2="*"),1,),)+
IF(LEN($I$2),IF(OR($I$2=I3,$I$2="*"),1,),)+
IF(LEN($J$2),IF(OR($J$2=J3,$J$2="*"),1,),)+
IF(LEN($K$2),IF(OR($K$2=K3,$K$2="*"),1,),)+
IF(LEN($L$2),IF(OR($L$2=L3,$L$2="*"),1,),)+
IF(LEN($M$2),IF(OR($M$2=M3,$M$2="*"),1,),)+
IF(LEN($N$2),IF(OR($N$2=N3,$N$2="*"),1,),)+
IF(LEN($O$2),IF(OR($O$2=O3,$O$2="*"),1,),)+
IF(LEN($P$2),IF(OR($P$2=P3,$P$2="*"),1,),)+
IF(LEN($Q$2),IF(OR($Q$2=Q3,$Q$2="*"),1,),)+
IF(LEN($R$2),IF(OR($R$2=R3,$R$2="*"),1,),)+
IF(LEN($S$2),IF(OR($S$2=S3,$S$2="*"),1,),)+
IF(LEN($T$2),IF(OR($T$2=T3,$T$2="*"),1,),)+
IF(LEN($U$2),IF(OR($U$2=U3,$U$2="*"),1,),)+
IF(LEN($V$2),IF(OR($V$2=V3,$V$2="*"),1,),)+
IF(LEN($W$2),IF(OR($W$2=W3,$W$2="*"),1,),)+
IF(LEN($X$2),IF(OR($X$2=X3,$X$2="*"),1,),)+
IF(LEN($Y$2),IF(OR($Y$2=Y3,$Y$2="*"),1,),)+
IF(LEN($Z$2),IF(OR($Z$2=Z3,$Z$2="*"),1,),)+
IF(LEN($AA$2),IF(OR($AA$2=AA3,$AA$2="*"),1,),)+
IF(LEN($AB$2),IF(OR($AB$2=AB3,$AB$2="*"),1,),)+
IF(LEN($AC$2),IF(OR($AC$2=AC3,$AC$2="*"),1,),)+
IF(LEN($AD$2),IF(OR($AD$2=AD3,$AD$2="*"),1,),)+
IF(LEN($AE$2),IF(OR($AE$2=AE3,$AE$2="*"),1,),)+
IF(LEN($AF$2),IF(OR($AF$2=AF3,$AF$2="*"),1,),)+
IF(LEN($AG$2),IF(OR($AG$2=AG3,$AG$2="*"),1,),)+
IF(LEN($AH$2),IF(OR($AH$2=AH3,$AH$2="*"),1,),)+
IF(LEN($AI$2),IF(OR($AI$2=AI3,$AI$2="*"),1,),)+
IF(LEN($AJ$2),IF(OR($AJ$2=AJ3,$AJ$2="*"),1,),)+
IF(LEN($AK$2),IF(OR($AK$2=AK3,$AK$2="*"),1,),)+
IF(LEN($AL$2),IF(OR($AL$2=AL3,$AL$2="*"),1,),)+
IF(LEN($AM$2),IF(OR($AM$2=AM3,$AM$2="*"),1,),)+
IF(LEN($AN$2),IF(OR($AN$2=AN3,$AN$2="*"),1,),)+
IF(LEN($AO$2),IF(OR($AO$2=AO3,$AO$2="*"),1,),)+
IF(LEN($AP$2),IF(OR($AP$2=AP3,$AP$2="*"),1,),)+
IF(LEN($AQ$2),IF(OR($AQ$2=AQ3,$AQ$2="*"),1,),)+
IF(LEN($AR$2),IF(OR($AR$2=AR3,$AR$2="*"),1,),)+
IF(LEN($AS$2),IF(OR($AS$2=AS3,$AS$2="*"),1,),)+
IF(LEN($AT$2),IF(OR($AT$2=AT3,$AT$2="*"),1,),)+
IF(LEN($AU$2),IF(OR($AU$2=AU3,$AU$2="*"),1,),)+
IF(LEN($AV$2),IF(OR($AV$2=AV3,$AV$2="*"),1,),)+
IF(LEN($AW$2),IF(OR($AW$2=AW3,$AW$2="*"),1,),)+
IF(LEN($AX$2),IF(OR($AX$2=AX3,$AX$2="*"),1,),)+
IF(LEN($AY$2),IF(OR($AY$2=AY3,$AY$2="*"),1,),)+
IF(LEN($AZ$2),IF(OR($AZ$2=AZ3,$AZ$2="*"),1,),)
and here is "Formula Generator" sheet for that

DISTINCT, MAX and list value from join table

How to combine distinct and max within join table below?
Table_details_usage
UID | VE_NO | START_MILEAGE | END_MILEAGE
------------------------------------------------
1 | ASD | 410000 | 410500
2 | JWQ | 212000 | 212350
3 | WYS | 521000 | 521150
4 | JWQ | 212360 | 212400
5 | ASD | 410520 | 410600
Table_service_schedule
SID | VE_NO | SV_ONMILEAGE | SV_NEXTMILEAGE
------------------------------------------------
1 | ASD | 400010 | 410010
2 | JWQ | 212120 | 222120
3 | WYS | 511950 | 521950
4 | JWQ | 212300 | 222300
5 | ASD | 410510 | 420510
How to get display as below (only max value)?
Get Max value from Table_service_schedule (SV_NEXTMILEAGE) and Get Max value from Table_details_usage (END_MILEAGE)
SID | VE_NO | SV_NEXTMILEAGE | END_MILEAGE
--------------------------------------------
5 | ASD | 420510 | 410600
4 | JWQ | 222300 | 212400
3 | WYS | 521950 | 521150
Something in the lines of:
SELECT
SID,
VE_NO,
SV_NEXTMILEAGE,
(select max(END_MILEAGE) from Table_details_usage d where d.VE_NO = s.VE_NO) END_MILEAGE
FROM Table_service_schedule s
WHERE SID = (SELECT max(SID) FROM Table_service_schedule s2 WHERE s2.VE_NO = s.VE_NO)
Probably could need to change the direct value ov SV_NEXTMILEAGE to max as well if the id:s aren't in order...

PSQL code missing

My problem on getting one row shown with two null values.
FROM tuotemerkki;
tmtunnus | tmnimi | maa
----------+----------+-------------
1 | McCee | Yhdysvallat
2 | KooTek | Italia
3 | Giardino | Italia
(3 rows)
FROM tuote;
ttunnus | tnimi | kuvaus | suositushinta | tmtunnus
---------+-----------------------+--------------------+---------------+----------
111 | Trimmeri TRCee | tehokas 4-tahtinen | 179.00 | 1
112 | Trimmerisiima Cee | laadukas siima | 6.99 | 1
113 | Moottorisaha MSCee RR | robusti ja raskas | 559.00 | 1
114 | Trimmerisiima Y | yleissiima | 3.99 | 2
115 | Lapio L | kevyt yleislapio | 23.95 | 2
(5 rows)
I need to get this selected with the NULL VALUE on giardino from tmnimi.
tmnimi | tnimi | kuvaus
----------+-----------------------+--------------------
McCee | Trimmeri TRCee | tehokas 4-tahtinen
McCee | Trimmerisiima Cee | laadukas siima
McCee | Moottorisaha MSCee RR | robusti ja raskas
KooTek | Trimmerisiima Y | yleissiima
KooTek | Lapio L | kevyt yleislapio
Giardino | |
(6 rows)
I get only this selected
SELECT tmnimi, tnimi, kuvaus
FROM tuote
CROSS JOIN tuotemerkki
WHERE tuote.tmtunnus = tuotemerkki.tmtunnus;
tmnimi | tnimi | kuvaus
--------+-----------------------+--------------------
McCee | Trimmeri TRCee | tehokas 4-tahtinen
McCee | Trimmerisiima Cee | laadukas siima
McCee | Moottorisaha MSCee RR | robusti ja raskas
KooTek | Trimmerisiima Y | yleissiima
KooTek | Lapio L | kevyt yleislapio
(5 rows)
Use a left join between the two tables:
SELECT
t1.tmnimi,
t2.tnimi,
t2.kuvaus
FROM tuotemerkki t1
LEFT JOIN tuote t2
ON t1.tmtunnus = t2.tmtunnus
When you left join from tuotemerkki to tuote, then every record in the former table is guaranteed to appear in the result set. Since the Giardino record does not match to anything in the tuote table, all the columns from that table would have a NULL value for the Giardino record.

Finding root of a tree in a directed graph

I have a tree structure like node(1)->node(2)->node(3). I have name as an property used to retrieve a node.
Given a node say node(3), i wanna retrieve node(1).
Query tried :
MATCH (p:Node)-[:HAS*]->(c:Node) WHERE c.name = "node 3" RETURN p LIMIT 5
But, not able to get node 1.
Your query will not only return "node 1", but it should at least include one path containing it. It's possible to filter the paths to only get the one traversing all the way to the root, however:
MATCH (c:Node {name: "node 3"})<-[:HAS*0..]-(p:Node)
// The root does not have any incoming relationship
WHERE NOT (p)<-[:HAS]-()
RETURN p
Note the use of the 0 length, which matches all cases, including the one where the start node is the root.
Fun fact: even if you have an index on Node:name, it won't be used (unless you're using Neo4j 3.1, where it seems to be fixed since 3.1 Beta2 at least) and you have to explicitly specify it.
MATCH (c:Node {name: "node 3"})<-[:HAS*0..]-(p:Node)
USING INDEX c:Node(name)
WHERE NOT (p)<-[:HAS]-()
RETURN p
Using PROFILE on the first query (with a numerical id property instead of name):
+-----------------------+----------------+------+---------+-------------------------+----------------------+
| Operator | Estimated Rows | Rows | DB Hits | Variables | Other |
+-----------------------+----------------+------+---------+-------------------------+----------------------+
| +ProduceResults | 0 | 1 | 0 | p | p |
| | +----------------+------+---------+-------------------------+----------------------+
| +AntiSemiApply | 0 | 1 | 0 | anon[23], c -- p | |
| |\ +----------------+------+---------+-------------------------+----------------------+
| | +Expand(All) | 1 | 0 | 3 | anon[58], anon[67] -- p | (p)<-[:HAS]-() |
| | | +----------------+------+---------+-------------------------+----------------------+
| | +Argument | 1 | 3 | 0 | p | |
| | +----------------+------+---------+-------------------------+----------------------+
| +Filter | 1 | 3 | 3 | anon[23], c, p | p:Node |
| | +----------------+------+---------+-------------------------+----------------------+
| +VarLengthExpand(All) | 1 | 3 | 5 | anon[23], p -- c | (c)<-[:HAS*]-(p) |
| | +----------------+------+---------+-------------------------+----------------------+
| +Filter | 1 | 1 | 3 | c | c.id == { AUTOINT0} |
| | +----------------+------+---------+-------------------------+----------------------+
| +NodeByLabelScan | 3 | 3 | 4 | c | :Node |
+-----------------------+----------------+------+---------+-------------------------+----------------------+
Total database accesses: 18
and on the second one:
+-----------------------+----------------+------+---------+-------------------------+------------------+
| Operator | Estimated Rows | Rows | DB Hits | Variables | Other |
+-----------------------+----------------+------+---------+-------------------------+------------------+
| +ProduceResults | 0 | 1 | 0 | p | p |
| | +----------------+------+---------+-------------------------+------------------+
| +AntiSemiApply | 0 | 1 | 0 | anon[23], c -- p | |
| |\ +----------------+------+---------+-------------------------+------------------+
| | +Expand(All) | 1 | 0 | 3 | anon[81], anon[90] -- p | (p)<-[:HAS]-() |
| | | +----------------+------+---------+-------------------------+------------------+
| | +Argument | 1 | 3 | 0 | p | |
| | +----------------+------+---------+-------------------------+------------------+
| +Filter | 1 | 3 | 3 | anon[23], c, p | p:Node |
| | +----------------+------+---------+-------------------------+------------------+
| +VarLengthExpand(All) | 1 | 3 | 5 | anon[23], p -- c | (c)<-[:HAS*]-(p) |
| | +----------------+------+---------+-------------------------+------------------+
| +NodeUniqueIndexSeek | 1 | 1 | 2 | c | :Node(id) |
+-----------------------+----------------+------+---------+-------------------------+------------------+
Total database accesses: 13

Resources