cypher merge executed results java - java

I have two queries:
I run this query in one method
String query = "MATCH (g:Grid {name:'"+gridLocation+"'})<-[r:WILL_GO]-(t:Taxi)"
+ "WHERE r.reachedTime <= '"+userPickUp+"' RETURN t.name AS Taxi";
Result taxiWillGo = graphDb.execute(query);
And in another method
String query2 = "MATCH p=((g:Grid {name:'"+gridLocation+"'})-[r:TO*1..2]-(g2:Grid)), (g2)-[r2:LOCATION]-(t:Taxi) "
+ "WITH t, p, REDUCE(totalTime = 0, x IN RELATIONSHIPS(p) | totalTime + x.time) AS totalTime "
+ "WHERE totalTime <= 6 RETURN t.name as Taxi LIMIT 3";
Result taxiNeighbor = graphDb.execute(query2);
Both queries return the same element (a taxi), is it possible to merge both executed Results into a single one so at the end i have one "table" displaying all results.
WILL_GO Taxis:
+----------+
| Taxi |
+----------+
| "taxi 4" |
+----------+
NEIGHBOR Taxis:
+----------+
| Taxi |
+----------+
| "taxi 2" |
| "taxi 1" |
| "taxi 4" |
+----------+
e.g Merged Table WILL GO and NEIGHBOR
+----------+
| Taxi |
+----------+
| "taxi 2" |
| "taxi 1" |
| "taxi 4" |
+----------+
Thank you in advance!

You can use the UNION Cypher clause to combine the results of two queries: http://neo4j.com/docs/stable/query-union.html
MATCH ...
RETURN t
UNION
MATCH ...
RETURN t

Related

Postgresql Generate_series. Generate dates by month

I am using select
SELECT
asl.id, asl.outstanding_principal as outstandingPrincipal, the_date as theDate, asl.interest_rate as interestRate, asl.interest_payment as interestPayment, asl.principal_payment as principalPayment,
asl.total_payment as totalPayment, asl.actual_delta as actualDelta, asl.outstanding_usd as outstandingUsd, asl.disbursement, asl.floating_index_rate as floatingIndexRate,
asl.upfront_fee as upfrontFee, asl.commitment_fee as commitmentFee, asl.other_fee as otherFee, asl.withholding_tax as withholdingTax, asl.default_fee as defaultFee,
asl.prepayment_fee as prepaymentFee, asl.total_out_flows as totalOutFlows, asl.net_flows as netFlows, asl.modified, asl.new_row as newRow, asl.interest_payment_modified as
interestPaymentModified, asl.date, asl.amortization_schedule_initial_id as amortizationScheduleInitialId, asl.tranche_id as trancheId, asl.user_id as userId, tr.local_currency_id as localCurrencyId,
f.facility_id
FROM
GENERATE_SERIES
(
(SELECT MIN(ams.date) FROM amortization_schedules ams),
(SELECT MAX(ams.date) + INTERVAL '1' MONTH FROM amortization_schedules ams),
'1 MONTH'
) AS tab (the_date)
FULL JOIN amortization_schedules asl on to_char(the_date, 'yyyy-mm') = to_char(asl.date, 'yyyy-mm')
LEFT JOIN tranches tr ON asl.tranche_id = tr.id
LEFT JOIN facilities f on tr.facility_id = f.id
In this select, I'm using generate_series to get each month since there are no records in the database for each month. But the matter is that this select gives me superfluous results. I use this select in my Spring Boot application. But the fact is that I need all the data, and for example only with a certain facility_id , and when I insert a condition
WHERE f.id = :id and tr.tranche_number_id = :trancheNumberId
My generate_series stops working (as I understand it, because I set certain conditions for generating a request) and instead of 30 lines, I get only 3.
How do I keep the ability to generate the theDate by month, with the ability to select specific IDs
I tried different options.
With this option:
FULL JOIN amortization_schedules asl on to_char(the_date, 'yyyy-mm') = to_char(asl.date, 'yyyy-mm')
| id | outstantandingprincipal | thedate |
-------------------------------------------------------------------
| 1 | 10000 | 2022-05-16 00:00:00.000000 |
| 2 | 50000 | 2023-05-16 00:00:00.000000 |
| 3 | 0 | 2024-05-16 00:00:00.000000 |
In this case, it does not work correctly, since months are not generated and only three lines are displayed (if it is (the_date, 'yyyy-MM') = to_char(asl.date, 'yyyy-MM')).
If I change to (the_date, 'yyyy') = to_char(asl.date, 'yyyy') then the generation works, but it doesn't work correctly because it is year oriented.
| id | outstantandingprincipal | thedate |
-------------------------------------------------------------------
| 1 | 10000 | 2022-05-16 00:00:00.000000 |
| 1 | 10000 | 2022-06-16 00:00:00.000000 |
| 1 | 10000 | 2022-06-16 00:00:00.000000 |
| 1 | 10000 | 2022-07-16 00:00:00.000000 |
... ... ....
| 1 | 10000 | 2022-12-16 00:00:00.000000 |
| 2 | 50000 | 2023-01-16 00:00:00.000000 |
| 2 | 50000 | 2023-02-16 00:00:00.000000 |
| 2 | 50000 | 2023-03-16 00:00:00.000000 |
| 2 | 50000 | 2023-04-16 00:00:00.000000 |
... ... ....
| 3 | 0 | 2024-01-16 00:00:00.000000 |
but it should be:
| id | outstantandingprincipal | thedate |
-------------------------------------------------------------------
| 1 | 10000 | 2022-05-16 00:00:00.000000 |
| 1 | 10000 | 2022-06-16 00:00:00.000000 |
| 1 | 10000 | 2022-06-16 00:00:00.000000 |
| 1 | 10000 | 2022-07-16 00:00:00.000000 |
... ... ....
| 1 | 10000 | 2023-04-16 00:00:00.000000 |
| 2 | 50000 | 2023-05-16 00:00:00.000000 |
| 2 | 50000 | 2023-06-16 00:00:00.000000 |
| 2 | 50000 | 2023-07-16 00:00:00.000000 |
| 2 | 50000 | 2023-08-16 00:00:00.000000 |
... ... ....
| 3 | 0 | 2024-05-16 00:00:00.000000 |
| 3 | 0 | 2024-06-16 00:00:00.000000 |
| 3 | 0 | 2024-07-16 00:00:00.000000 |
I'm making a few intuitive leaps here, so if something looks off it might be because I don't have the entire picture.
From what I can tell you want the amortization schedule starting from the "date" for each ID and then going out a specific amount of time. I am guessing it is not truly the max date in that entire table, and that it varies by ID. In your example you went out one year, so for now I'm going with that.
You can use a generate_series inline, which will explode out each row. I believe something like this will give you the output you seek:
with schedule as (
select
id,
generate_series (date, date + interval '1 year', interval '1 month')::date as dt
from
amortization_schedules
)
select
asl.id, s.dt, asl.outstanding_principal
from
amortization_schedules asl
join schedule s on asl.id = s.id
JOIN tranches tr ON asl.tranche_id = tr.id
JOIN facilities f on tr.facility_id = f.id
WHERE
f.id = :id and
tr.tranche_number_id = :trancheNumberId
Is there another field that tells, by id, when the payments should end or one that will let us derive it (number of payments, payment end date, etc)?
One final note. If you use [left] outer joins and a where clause, as in below:
LEFT JOIN tranches tr ON asl.tranche_id = tr.id
LEFT JOIN facilities f on tr.facility_id = f.id
WHERE
f.id = :id and
tr.tranche_number_id = :trancheNumberId
You have effectively nullified the "left" and made these inner joins. In this case, get rid of "left," not because it will return wrong results but because it misleads. You are saying those fields must have those specific values, which means they must first exist. That's an inner join.
If you truly wanted these as left joins, this would have been more appropriate, but I don't think this is what you meant:
LEFT JOIN tranches tr ON
asl.tranche_id = tr.id and
tr.tranche_number_id = :trancheNumberId
LEFT JOIN facilities f on
tr.facility_id = f.id and
f.id = :id

Finding duplicates from column in the rest of database with JPA

I've got few columns in my db. I want to choose one and then return all of the records where values are duplicated. So I want to like, get one column and check which values from my column appeared from the rest of the db. Then return this records. Let's say that database looks like this:
id;col1;col2;col3;col4
'1','ab','cd','ef','1'
'2','ad','bg','ee','5'
'3','xx','bg','cc','6'
'4','vv','zz','ff','4'
'5','zz','ee','gg','4'
'6','zz','vv','zz','2'
'7','vv','aa','bb','8'
'8','ww','nn','zz','4'
'9','zz','yy','ff','9'
'10','qq','oo','ii','3'
and I want my result for col1 to look like so
4,'vv','zz','ff',4
5,'zz','ee','gg',4
6,'zz','vv','zz',2
7,'vv','aa','bb',8
9,'zz','yy','ff',9
Here we present the duplicates in 2 different ways. The first is the format you have requested, with additional information. The second is more concise.
create table t1(
id varchar(10),
col1 varchar(10),
col2 varchar(10),
col3 varchar(10),
col4 varchar(10));
insert into t1 values
('1','ab','cd','ef','1'),
('2','ad','bg','ee','5'),
('3','xx','bg','cc','6'),
('4','vv','zz','ff','4'),
('5','zz','ee','gg','4'),
('6','zz','vv','zz','2'),
('7','vv','aa','bb','8'),
('8','ww','nn','zz','4'),
('9','zz','yy','ff','9'),
('10','qq','oo','ii','3');
select * from t1;
id | col1 | col2 | col3 | col4
:- | :--- | :--- | :--- | :---
1 | ab | cd | ef | 1
2 | ad | bg | ee | 5
3 | xx | bg | cc | 6
4 | vv | zz | ff | 4
5 | zz | ee | gg | 4
6 | zz | vv | zz | 2
7 | vv | aa | bb | 8
8 | ww | nn | zz | 4
9 | zz | yy | ff | 9
10 | qq | oo | ii | 3
with cte as(
select
id,
col1,
col2,
col3,
col4,
row_number() over
( partition by col1
order by id desc) r1,
row_number() over
( partition by col2
order by id desc) r2,
row_number() over
( partition by col3
order by id desc) r3,
row_number() over
( partition by col4
order by id desc) r4
from t1
)
select *
from cte
where
r1 > 1
or r2 > 1
or r3 > 1
or r4 > 1;
id | col1 | col2 | col3 | col4 | r1 | r2 | r3 | r4
:- | :--- | :--- | :--- | :--- | -: | -: | -: | -:
6 | zz | vv | zz | 2 | 2 | 1 | 2 | 1
5 | zz | ee | gg | 4 | 3 | 1 | 1 | 2
4 | vv | zz | ff | 4 | 2 | 1 | 2 | 3
2 | ad | bg | ee | 5 | 1 | 2 | 1 | 1
select 'col1' as "column",
col1 "value",
count(id) "count"
from t1 group by col1
having count(id)>1
union all
select 'col2',col2, count(id)
from t1 group by col2
having count(id)>1
union all
select 'col3',col3, count(id)
from t1 group by col3
having count(id)>1
union all
select 'col4',col4, count(id)
from t1 group by col4
having count(id)>1
order by "column","value";
column | value | count
:----- | :---- | ----:
col1 | vv | 2
col1 | zz | 3
col2 | bg | 2
col3 | ff | 2
col3 | zz | 2
col4 | 4 | 3
db<>fiddle here

Grouping by value with separation of the output

I have a this type of data:
| company_id | role_id |
| 1 | 1 |
| 2 | 2 |
| 1 | 2 |
Here's my query which selects one company id and passed as an argument role id.
SELECT company_id AS companyId, COUNT(role_id) AS usersNumber
FROM companies
WHERE role_id = :userId
GROUP BY companyId
Where :userId is an argument passed from JPA.
Which produces something like this:
| company_id | passed_role_id_count |
| 1 | 1 |
| 2 | 1 |
What I want to achieve is to have the output like this:
| company_id | first_role_count | second_role_count |
| 1 | 1 | 1 |
| 2 | 0 | 1 |
Is it possible to have the output like this? Or maybe is it better to select all from DB and then group using Java Streams?
Use a filtered aggregation:
SELECT company_id AS companyId,
COUNT(*) filter (where role_id = 1) AS first_role_count,
COUNT(*) filter (where role_id = 2) AS second_role_count
FROM companies
WHERE role_id = :userId
GROUP BY companyId
With the hint from #jarlh I managed to solve my problem:
SELECT eu.company_id,
SUM(CASE WHEN eu.role_id = 2 THEN 1 ELSE 0 END) AS "first_role",
SUM(CASE WHEN eu.role_id = 3 THEN 1 ELSE 0 END) AS "second_role"
FROM users eu
GROUP BY eu.company_id;

How to select next record and previous record in SQLite?

I have been searching like forever
I am using min and max for the last and and first record but how do I get the next/ record? I have a column name rowid it is the pk and auto incremented by one every time a user registers
| rowid | Name |
| 1 | John |*
| 2 | Mark |
| 3 | Peter|
| 4 | Help |
so if I click the next button I wanted to select mark which is in rowid 2
| rowid | Name |
| 1 | John |
| 2 | Mark |*
| 3 | Peter|
| 4 | Help |
but if I click the next button twice I want to be in rowid 4
| rowid | Name |
| 1 | John |
| 2 | Mark |
| 3 | Peter|
| 4 | Help |*
how do I do that? by the way I don't have fixed rows since I have a registration function
so here's my code
JButton btnNextLast = new JButton(">>");
btnNextLast.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try{
String sQuery = "select * from accountinfo where rowid = (SELECT MAX(rowid) FROM accountinfo)";
PreparedStatement prst = connection.prepareStatement(sQuery);
ResultSet rs = prst.executeQuery();
lblSID.setText(rs.getString("sid"));
lblfirst.setText(rs.getString("last"));
lblLast.setText(rs.getString("first"));
lblmiddle.setText(rs.getString("middle"));
lblbirth.setText(rs.getString("birth"));
lblcontact.setText(rs.getString("contact"));
}catch(Exception qwe){
}
}
});
I've tried
select rowid
from accountinfo
where rowid >1
order by rowid
limit 1
but no luck
and if I remove order by rowid limit 1. It just show the next record which is 2 and never function again

I need help re-writing this method using a Java Array or ArrayList

I have a database table called trading_history which looks like this:
+----------+---------+---------+-----------+------------+
| table_id | item_id | user_id | item_type | phone |
+----------+---------+---------+-----------+------------+
| 1 | 4564704 | 629 | 2 | 3656284 |
| 2 | 4564705 | 629 | 1 | 3656284 |
| 3 | 4564773 | 569 | 1 | 8111111 |
| 4 | 4564792 | 351 | 2 | 0804609120 |
| 5 | 4564825 | 569 | 1 | 8111111 |
| 6 | 4564853 | 646 | 1 | 1111144 |
| 7 | 4564874 | 646 | 1 | 1111144 |
| 8 | 4564944 | 646 | 1 | 1111144 |
| 9 | 4564964 | 105 | 2 | 3614794 |
| 10 | 4564965 | 105 | 1 | 3614794 |
+----------+---------+---------+-----------+------------+
Fields table_id, and item_id are unique. The table records items sold by a user. Item_ids are sequential for each user, meaning that the top most item for a user is the item he sold first while the bottom most item represents the most recent item he sold.
From the above table, I want to periodically remove all items and leave only 20 most recent items sold by the user. That is, if a user has sold 100 items, I want to remove the 80 oldest items and leave him with 20. For those who have sold less than 20 in that period nothing will be removed.
I accomplished that by writing a SQL statement like this:
CREATE TABLE IF NOT EXISTS trading_history_archive LIKE trading_history;
INSERT INTO trading_history_archive
SELECT table_id, item_id , user_id,item_type,phone FROM trading_history
WHERE item_id NOT IN (
SELECT item_id
FROM trading_history as tdg
WHERE 20 > (
SELECT count(*)
FROM trading_history AS tdg1
WHERE tdg.user_id = tdg1.user_id
AND tdg.item_id > tdg1.item_id )
ORDER BY item_id DESC );
DELETE a FROM trading_history a INNER JOIN trading_history_archive b ON a.table_id = b.table_id;
However, this needs to be part of a Java application to be managed by the Scheduler. I tried creating a method using the SQL statements, but it looks clumsy and I fear SQL injection:
public class ArchiveTrading {
private final static Logger LOG = Logger.getLogger (ArchiveTrading.class);
private int sessionsArchived = 0;
.....
.....
.....
archiveTradingHistory(con, yymm);
.....
.....
private void archiveTradingHistory(Connection con, String yymm) {
try {
SqlUtil.runSqlUpdate(con, "CREATE TABLE IF NOT EXISTS trading_history_archive LIKE trading_history");
LOG.info("Finihsed creating table");
int inserted = SqlUtil.runSqlUpdate(con, "INSERT INTO trading_history_archive " +
" SELECT table_id, item_id , user_id,item_type,phone FROM trading_history "+
" WHERE item_id NOT IN ( "+
" SELECT item_id ( " +
" FROM trading_history as tdg " +
" WHERE 20 > ( "+
" SELECT count(*) "+
" FROM trading_history AS tdg1 "+
" WHERE tdg.user_id = tdg1.user_id "+
" AND tdg.item_id > tdg1.item_id ) "+
" ORDER BY item_id DESC ) ");
LOG.info("trading_history Inserted: " + inserted);
int deleted = SqlUtil.runSqlUpdate(con, "DELETE a FROM trading_history a INNER JOIN trading_history_archive b ON a.table_id = b.table_id");
LOG.info("trading_history Deleted: " + deleted);
} catch (NumberFormatException e) {
LOG.error(e.getMessage());
} catch (CustomDAOException e) {
LOG.error(e.getMessage());
}
}
.....
......
}
Someone help me improve this so I can survive work politics.

Categories