This the following SQL Query
select count(distinct Descendent_id) from
(
select *
from v.ABC a
left join v.XYZ b
on a.Target_id=b.Ancestor_id
) t
where t.Target_id = 1234;
Edit
There's actually no relationship between the two tables / nodes. I'll explain -
Let's assume Table B has Ancestor_Id and Descendent_id which has some relationship between them we can call it [children]
Ancestor_Id - 101 --[children]--> Descendent_Id - 101.1
Ancestor_Id - 101 --[children]--> Descendent_Id - 101.2
Table A has only Target_Id which are the same as of Table B,
Eg - Table A - Target_Id = 101 | Table - B Ancestor_Id = 101
Note -
Table A doesn't have any relationship with Table B.
So I need to join the two tables / nodes with Target_Id and Ancestor_ID and what ultimately i want is DISTINCT COUNT of Descendent_Id from Table B which has a [children] relationship with Ancestor_Id.
Also from the SQL Query if you can see Descendent_id doesn't has any
alias pre-pended to it like b.Descendent, how do I achieve the same in
Neo4j.
Kindly let me know if I've still not cleared the doubt properly.
I am very new in CYPHER - Neo4j, KINDLY HELP!
[UPDATED]
The following Cypher will get the number of distinct D_id values in the "left join" of abc and xyz nodes having the specified ID.
MATCH (a:abc) WHERE a.id = $id
OPTIONAL MATCH (b:xyz) WHERE b.abc_id = $id
WITH COLLECT(a.D_id)+COLLECT(b.D_id) AS ids
UNWIND ids AS id
RETURN COUNT(DISTINCT id) AS D_id_count
I assume that abc nodes store the ID in an id property, and xyz nodes store it in an abc_id property. I also assume that the desired ID value is passed as an id parameter.
Note: this query would be faster if you created indexes on:
:abc(id)
:xyz(abc_id)
Related
I am using PHP to pull data from specific locations and trying to setup the SQL inquiry to look at a specific location by the rank. The inquiry needs to have two tables joined to be able to filter the results. The first table has column that I want the ranking to be based on where the second table has the filter. The tables I have are similar to
table1
itemA* | itemB | itemC | itemD | itemE | itemRank
table2
itemA* | itemB | itemC | itemD
* primary key
My ultimate goal is to get the row number/rank of an item in itemA (primary key) column.
This is my current code.
SELECT ROW_NUMBER() OVER (ORDER BY table1.itemC DESC) AS table1.itemRank
FROM table1 JOIN table2 WHERE table1.itemA = table2.itemA AND table2.itemD = "Y";
The column table1.itemRank doesn't have any data in it and want it to be able to change depending on the column I would like to rank by - itemB, itemC, itemD and itemE are all different types of data values of each of the primary keys/itemA.
This is the error that pops up:
1. An alias was previously found. (near "`itemRank`" at position 55)
2. An alias was expected. (near " " at position 54)
3. Unexpected token. (near "`itemRank`" at position 55)
You cannot use table1. as an alias. table1 already refers to table1. This query will return itemA from table1 with the rank, which is what I understand you are trying to do.
SELECT table1.itemA, ROW_NUMBER() OVER (ORDER BY table1.itemC DESC) AS itmerank
FROM table1 JOIN table2 WHERE table1.itemA = table2.itemA AND table2.itemD = "Y";
I have a new column in my database and I need fill it up with the value of the same column from one specific row. I want to create a feature "copy to all"
For example add the same price to all the products taken from the first row:
ID NAME PRICE
1 PROD1 5
2 PROD2 0
3 PROD3 0
4 PROD4 0
I am trying to select the PRICE of the first row (ID 1) and copy it to all the other rows.
I have tried:
UPDATE PRODUCTS SET PRICE = (select PRICE from PRODUCTS where ID = 1);
I want to end up with this
ID NAME PRICE
1 PROD1 5
2 PROD2 5
3 PROD3 5
4 PROD4 5
But I get this error:
Table 'PRODUCTS' is specified twice,
both as a target for 'UPDATE' and as a separate source for data
I tried specifying each table separately
UPDATE PRODUCTS as a SET a.PRICE = (select b.PRICE from PRODUCTS as b where b.ID = 1);
But I get the same error.
Table 'a' is specified twice,
both as a target for 'UPDATE' and as a separate source for data
Maybe I have to create a temporary table and copy from it?
Any hints on how to accomplish this?
Thanks.
You can do it by nesting the select query:
UPDATE PRODUCTS
SET PRICE = (
select PRICE from (select PRICE from PRODUCTS where ID = 1) t
);
See the demo.
Another way to do it, with a self CROSS JOIN:
UPDATE PRODUCTS p CROSS JOIN (
select PRICE from PRODUCTS where ID = 1
) t
SET p.PRICE = t.PRICE;
See the demo.
This wouldn't work logically, as SQL would try to fetch the data it is updating.
Try running your nested statement select PRICE from PRODUCTS where ID = 1 seperately, saving the response and then running your main statement: "UPDATE PRODUCTS SET PRICE = " + newPrice
If this is a SQL script, i suggest you to break it into 2 queries using a variable:
select #var := PRICE from PRODUCTS where ID = 1;
UPDATE PRODUCTS SET PRICE = #var;
Variables are much more easier than temporary table in my opinion.
I've not fully tested, but the syntax should be that
After looking at many answers on other posts and websites, (none of them had the precise answer), I found the solution with this query, and yes we need temp tables:
CREATE TEMPORARY TABLE tmptable SELECT ID, PRICE FROM PRODUCTS WHERE ID = 1;
UPDATE PRODUCTS SET `PRICE` = (select tmptable.`PRICE` from tmptable where tmptable.ID = 1);
BUT! #forpas solution's is really good and works without creating a temp table.
enjoy.
NEW question: is the temp table removed automatically? Leave me a comment.
Cheers
I have 3 tables that I am using and need to make a query to return data from one table based on the value of a single column in the second table.
tbl_user
ID
login
pass
active
mscID
tbl_master
ID
name
training_date
MSCUnit
Active
tbl_msc
mscID
mscName
my current SQL statement:
SELECT
tbl_master.ID,
tbl_master.name,
tbl_master.training_date,
tbl_master.MSCUnit,
tbl_master.active,
tbl_user.mscID
FROM
tbl_master,
tbl_user
WHERE
tbl_master.active = 1 AND tbl_master.MSCUnit = tbl_user.mscID
The values stored in tbl_msc.mscID is a varchar(11) and it contains a string similar to A00 or A19. This is also the Primary key in the table.
The values stored in tbl_user.mscID matches that of tbl_msc.mscID. The values stored in tbl_master.UnitMSC also matches that of tbl_msc.mscID.
My goal is to return all records from tbl_master where the currently logged in user has the same mscID. The problem I am having is the statement returns all records in tbl_master.
I have tried several different join statements and for some reason, I cannot get this to filter correctly.
I am missing something. Any assistance in the SQL statement would be appreciated.
Thanks,
Will
You should be writing this using joins. I don't know how you know who the current user is, but the idea is to join the three tables together:
SELECT m.ID, m.name, m.training_date, m.MSCUnit, m.active,
u.mscID
FROM tbl_master m JOIN
tbl_user u
ON m.MSCUnit = u.mscID JOIN
tbl_msc msc
ON msc.mscID = u.msc_ID
WHERE m.active = 1 AND msc.mscName = ?;
Notice the use of proper, explicit, standard JOIN syntax and table aliases.
Select a.*, b.userid from
table_master a, table_user b where
a.mscunit in (select mscid from
table_user where active=1)
This should point you in the right direction.
I have a table with a composite key composed of 2 columns, say Name and ID. I have some service that gets me the keys (name, id combination) of the rows to keep, the rest i need to delete. If it was with only 1 row , I could use
delete from table_name where name not in (list_of_valid_names)
but how do I make the query so that I can say something like
name not in (valid_names) and id not in(valid_ids)
// this wont work since they separately dont identity a unique record or will it?
Use mysql's special "multiple value" in syntax:
delete from table_name
where (name, id) not in (select name, id from some_table where some_condition);
If your list is a literal list, you can still use this approach:
delete from table_name
where (name, id) not in (select 'john', 1 union select 'sally', 2);
Actually, no I retract my comment about needing special juice or being stuck with (AND OR'ing all your options).
Since you have a list of values of what you want to retain, dump that into a temporary table. Then do a delete against the base table for what does not exist in the temporary table (left outer join). I suck at mysql syntax or I'd cobble together your query. Psuedocode is approximate
DELETE
B
FROM
BASE B
LEFT OUTER JOIN
#RETAIN R
ON R.key1 = B.key1
AND R.key2 = B.key
WHERE
R.key1 IS NULL
The NOT EXISTS version:
DELETE
b
FROM
BaseTable b
WHERE
NOT EXISTS
( SELECT
*
FROM
RetainTable r
WHERE
(r.key1, r.key2) = (b.key1, b.key2)
)
I have 2 tables: tbl_taxclasses, tbl_taxclasses_regions
This is a one to many relationship, where the main record ID is classid.
I have a column inside the first table called regionscount
So, I create a Tax Class, in table 1. Then I add regions/states in table 2, assigning the classid to each region.
I perform a SELECT statement to count the regions with that same classid, and then I perform an UPDATE statement on tbl_taxclasses with that number. I update the regionscount column.
This means I'm writing 2 queries. Which is fine, but I was wondering if there was a way to do a SELECT statement inside the UPDATE statement, like this:
UPDATE `tbl_taxclasses` SET `regionscount` = [SELECT COUNT(regionsid) FROM `tbl_taxclasses_regions` WHERE classid = 1] WHERE classid = 1
I'm reaching here, since I'm not sure how robust MySQL is, but I do have the latest version, as of today. (5.5.15)
You could use a non-correlated subquery to do the work for you:
UPDATE
tbl_taxclasses c
INNER JOIN (
SELECT
COUNT(regionsid) AS n
FROM
tbl_taxclasses_regions
GROUP BY
classid
) r USING(classid)
SET
c.regionscount = r.n
WHERE
c.classid = 1
Turns out I was actually guessing right.
This works:
UPDATE `tbl_taxclasses`
SET `regionscount` = (
SELECT COUNT(regionsid) AS `num`
FROM `tbl_taxclasses_regions`
WHERE classid = 1)
WHERE classid = 1 LIMIT 1
I just needed to replace my brackets [] with parenthesis ().