Moving Average from nested table using Oracle SQL - java

I'm trying to find the correct sql query based on the case below.
customer_id
unit_id
NAV
DATE
16
1254
10
2020-05-01
17
1253
20
2020-05-02
18
1253
30
2020-05-03
16
1254
20
2020-05-02
16
1254
30
2020-05-03
17
1253
20
2020-05-02
17
1255
30
2020-05-03
16
1254
20
2020-05-04
From the table above, the AVERAGE_NAV can be found by moving average since the first date unit purchased. So, if I want to find moving average NAV for spesific data of customer_id and unit_id from table ACCOUNTBALANCE, I use this query below.
SELECT
ACCBAL.CUSTOMER_ID,
ACCBAL.UNITTRUST_ID,
ACCBAL.INVACCT_ID,
ACCBAL.NAV,
AVG(ACCBAL.NAV)
OVER (
ORDER BY ACCBAL.BALANCEDATE
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
),
ACCBAL.CREATED_DATE
FROM WMS_UT_ACCOUNTBAL ACCBAL
WHERE
ACCBAL.CUSTOMER_ID=16 AND
ACCBAL.UNITTRUST_ID=1254
you can see the picture of the query in the link below.
query image
The result of the query is shown below.
customer_id
unit_id
NAV
DATE
Average_NAV
16
1254
10
2020-05-01
10
16
1254
20
2020-05-02
15
16
1254
30
2020-05-03
20
16
1254
20
2020-05-04
20
My question is, What is the query to find the average_NAV with all combined different customer_id and unit_id like this table below here.
customer_id
unit_id
NAV
DATE
average_NAV
16
1254
10
2020-05-01
10
17
1253
20
2020-05-02
20
18
1253
30
2020-05-03
30
16
1254
20
2020-05-02
15
16
1254
30
2020-05-03
20
17
1253
20
2020-05-02
20
17
1255
30
2020-05-03
30
16
1254
20
2020-05-04
20
the average_NAV must be based on the query result from the same customer_id and unitrust_id start from the first purchase. you can see that for customer_id=17 and unit_id=1255 has average_NAV=30 same as NAV since it's first purchase with those spesific customer_id and unit_id was 2020-05-03.
The main obstacle is how I can use where clause inside the outer SELECT because it's prohibited in oracle sql.
I have used CTE method (WITH) but still not what expected like below.
WITH ACCBAL (CUSTOMER_ID,UNITTRUST_ID,NAV, CREATED_DATE) AS
(SELECT ACCBAL1.CUSTOMER_ID, ACCBAL1.UNITTRUST_ID,
ACCBAL1.NAV, ACCBAL1.CREATED_DATE
FROM WMS_UT_ACCOUNTBAL ACCBAL1),
ACCBAL_AVERAGE_NAV (AVERAGE_NAV) AS
(SELECT AVG(ACCBAL2.NAV) OVER
(ORDER BY ACCBAL2.CREATED_DATE RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
FROM WMS_UT_ACCOUNTBAL ACCBAL2
WHERE ACCBAL2.UNITTRUST_ID=ACCBAL.UNITTRUST_ID
AND ACCBAL2.CUSTOMER_ID=ACCBAL.CUSTOMER_ID)
SELECT * FROM ACCBAL,ACCBAL_AVERAGE_NAV;
The query above is not working because it gives error of invalid identidier in WHERE clause.
Anyone can help me? Truly Appreciated. Thank you

You can include the PARTITION BY clause before ORDER BY.
Tested on db<>fiddle
SELECT
ACCBAL.CUSTOMER_ID,
ACCBAL.UNITTRUST_ID,
-- ACCBAL.INVACCT_ID,
ACCBAL.NAV,
ACCBAL.CREATED_DATE,
AVG(ACCBAL.NAV)
OVER (
PARTITION BY ACCBAL.CUSTOMER_ID, ACCBAL.UNITTRUST_ID
ORDER BY ACCBAL.CREATED_DATE
)
FROM WMS_UT_ACCOUNTBAL ACCBAL;

Related

Select from table and keep all lines with a certain column value in the bottom of the result

I have the following table:
name
age
pedro
11
duda
12
joao
7
pedro
9
guga
10
pedro
13
zelda
10
What I want is to select all entries here in which age >= 10, but at the same time keep all results which name = pedro in the last position, like this:
name
age
duda
12
guga
10
zelda
10
pedro
11
pedro
13
So there are two questions:
is it possible to do it with a select statement?
if so, is it possible to do this with JPA Repository simply naming a method?
is it possible to do it with a select statement?
Yes you can use where and order by with case like:
select *
from table
where age >= 10
order by case name when 'pedro' then 2 else 1 end
You can use CASE WHEN in the ORDER BY
SELECt * FROM tab1
WHERE age >= 10
ORDER BY CASE WHEN `name` = 'Pedro' THen 2 ELSE 1 END ASC, `name` ASC, `age` ASC
name | age
:---- | --:
duda | 12
guga | 10
zelda | 10
pedro | 11
pedro | 13
db<>fiddle here

Select the first duplicated element

I have 2 Classes in JAVA ( MODEL1 && MODEL2 )
As you can see here :
MODEL1_ID ACTN_DTE MODEL2_ID
---------- --------- --------------
1 14/11/19 18
1000 14/11/19 4
1001 14/11/19 19
1002 14/11/19 4
1003 14/11/19 4
1004 14/11/19 18
2000 14/11/19 5
I am trying to find a way with SQL Or HQL to get all elements from MODEL1 that have a list of MODEL2_ID , get only the first (min MODEL1_ID) MODEL1 per MODEL2_ID ( in case if it's duplucated ).
Exemple :
Input : MODEL2_ID in (18,4,19,5)
MODEL1_ID ACTN_DTE MODEL2_ID
---------- --------- --------------
1 14/11/19 18
1000 14/11/19 4
1001 14/11/19 19
2000 14/11/19 5
select MIN(MODEL1_ID) FROM table GROUP BY (MODEL2_ID)
It is possible that by "first" you mean the minimum actn_date and the question just has a useless sample of data (because all the values are the same).
If so, you can use aggregation with keep to get the first value by actn_date:
select model2_id, min(actn_date) as actn_date,
min(model1_id) keep (dense_rank first order by actn_date) as model1_id
from t
group by model2_id;

How to update two tables together in Oracle?

Query :
UPDATE TABLE_ONE
SET DATE=?, URL=?, TYPE=?, STATE=?, FEE=?, NAME=?, STATUS=?
WHERE ID=?";
Another table TABLE_TWO has columns - NAME, ID, FEE, STATUS, TOTAL,I want that on running update all above fields specified in query plus FEE, STATUS of TABLE_TWO gets updated together. I'm using Spring.
You can use trigger for say Table1 & write a trigger if any update on table 1 call trigger to update the Table 2 data.
it starts like..
create or replace TRIGGER trigger_name
after insert or update on Table1
for each row
...
For complete trigger refer (https://www.tutorialspoint.com/plsql/plsql_triggers.htm)
You can't update 2 tables (more than one) in one statement, instead use 2 statements and call them inside method annotated with #Transactional
#Transactional
public void updateTables() {
updateTableOne();
updateTableTwo();
}
commit will happen when method exists for both tables.
See more about using #Transactional in Spring
Other option is calling oracle procedure
Spring provides various ways of abstractions on JDBC to call database stored procedures.
Example
SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate)
.withProcedureName("MOVE_TO_HISTORY")
Solution 1: You can add both update statements in PLSQL procedure/function and execute the same in java code
Solution 2: You can add both update statements in a function and invoke the same
Oracle way of doing that is an instead-of trigger on a view.
Here's an example based on Scott's schema.
First, I'll create a view as a join of two tables, EMP and DEPT (that's where updating two tables together comes into a game):
SQL> create or replace view v_ed as
2 select d.deptno, e.empno, d.dname, e.ename, e.sal
3 from emp e join dept d on e.deptno = d.deptno;
View created.
Now, an instead-of trigger. I'm handling INSERT and UPDATE; you can add DELETE as well. It means that - when you insert into a view or update it, underlying tables will be the final target of those commands.
SQL> create or replace trigger trg_io_ed
2 instead of insert or update on v_ed
3 for each row
4 begin
5 if inserting then
6 insert into emp (deptno, empno, ename, sal)
7 values (:new.deptno, :new.empno, :new.ename, :new.sal);
8 insert into dept (deptno, dname)
9 values (:new.deptno, :new.dname);
10 elsif updating then
11 update emp set
12 deptno = :new.deptno,
13 ename = :new.ename,
14 sal = :new.sal
15 where empno = :new.empno;
16 update dept set
17 dname = :new.dname
18 where deptno = :new.deptno;
19 end if;
20 end;
21 /
Trigger created.
Some testing: insert:
SQL> insert into v_ed (deptno, empno, dname, ename, sal)
2 values (99, 100, 'test dept', 'Littlefoot', 1000);
1 row created.
SQL> select * From dept;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
99 test dept
SQL> select * From emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 17.12.80 800 20
7499 ALLEN SALESMAN 7698 20.02.81 1600 300 30
7521 WARD 7698 22.02.81 1250 500
7566 JONES MANAGER 7839 02.04.81 2975 20
7654 MARTIN SALESMAN 7698 28.09.81 1250 1400 30
7698 BLAKE MANAGER 7839 01.05.81 2850
7782 CLARK MANAGER 7839 09.06.81 2450 10
7788 SCOTT ANALYST 7566 09.12.82 3000 20
7839 KING PRESIDENT 17.11.81 5000 10
7844 TURNER SALESMAN 7698 08.09.81 1500 0 30
7876 ADAMS CLERK 7788 12.01.83 1100 20
7900 JAMES CLERK 7698 03.12.81 950 30
7902 FORD ANALYST 7566 03.12.81 3000 20
7934 MILLER CLERK 7782 23.01.82 1300 10
100 Littlefoot 1000 99
15 rows selected.
SQL>
Update:
SQL> update v_ed set ename = 'Bigfoot' where empno = 100;
1 row updated.
SQL> select * From emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 17.12.80 800 20
7499 ALLEN SALESMAN 7698 20.02.81 1600 300 30
7521 WARD 7698 22.02.81 1250 500
7566 JONES MANAGER 7839 02.04.81 2975 20
7654 MARTIN SALESMAN 7698 28.09.81 1250 1400 30
7698 BLAKE MANAGER 7839 01.05.81 2850
7782 CLARK MANAGER 7839 09.06.81 2450 10
7788 SCOTT ANALYST 7566 09.12.82 3000 20
7839 KING PRESIDENT 17.11.81 5000 10
7844 TURNER SALESMAN 7698 08.09.81 1500 0 30
7876 ADAMS CLERK 7788 12.01.83 1100 20
7900 JAMES CLERK 7698 03.12.81 950 30
7902 FORD ANALYST 7566 03.12.81 3000 20
7934 MILLER CLERK 7782 23.01.82 1300 10
100 Bigfoot 1000 99
15 rows selected.
SQL>
See if it helps.

Regexp for german phone number format

I try to get phone numbers from string in german format. But I don't get it to full run. The input text is a full HTML-Page with lots of content, not only the numbers.
Possible Formats:
(06442) 3933023
(02852) 5996-0
(042) 1818 87 9919
06442 / 3893023
06442 / 38 93 02 3
06442/3839023
042/ 88 17 890 0
+49 221 549144 – 79
+49 221 - 542194 79
+49 (221) - 542944 79
0 52 22 - 9 50 93 10
+49(0)121-79536 - 77
+49(0)2221-39938-113
+49 (0) 1739 906-44
+49 (173) 1799 806-44
0173173990644
0214154914479
02141 54 91 44 79
01517953677
+491517953677
015777953677
02162 - 54 91 44 79
(02162) 54 91 44 79
I have tried:
$regex = '~(?:\+?49|0)(?:\s*\d{3}){2}\s*\d{4,10}~';
if(preg_match_all($regex, $input_imprint , $matches)){
print_r($matches);
}
But it doesn't match only a few formats. I have no idea to do it.
Here is a regex to match all your formats.
I would suggest then to replace all unwanted characters and you got your desired result.
(\(?([\d \-\)\–\+\/\(]+)\)?([ .\-–\/]?)([\d]+))
If you need a minimum length to match your numbers, use this:
(\(?([\d \-\)\–\+\/\(]+){6,}\)?([ .\-–\/]?)([\d]+))
https://regex101.com/r/CAVex8/143
updated, thanks for the suggestion #Willi Mentzel
[0-9]*\/*(\+49)*[ ]*(\([0-9]+\))*([ ]*(-|–)*[ ]*[0-9]+)*
Check this link: https://regex101.com/r/CAVex8/1
May introduce some false positives.
This one solved my problem (extracting phone numers from emails):
r"\+?[0-9]+([0-9]|\/|\(|\)|\-| ){10,}"
A plus sign optional at the front, followed by at least 1 number, followed by at least 10 numbers or delimiting characters such as /, (, ) or - or a space.
(There is no official "smallest number of digits" for a telephone number, but I assume they are all at least 11 digits long)
I'm adding this because #Kakul 's solution matched any lien of my text, and using #despecial 's my code would not terminate. (I am guessing it is too computationally expensive for my pc)
This is no solution for the asked question, just an advice for matching phonenumbers!
If you are about to store telephone numbers for you first time, then limit the amount of different accepted formats. Get rid of these for example:
(06442) 3933023
042/ 88 17 890 0
+49(0)121-79536 - 77
02162 - 54 91 44 79
Why?
You need to test more possible ways of inputting an invalid value.
Those formats you absolutely need to concider according to DIN 5008:
0873 376461
03748 37682358
05444 347687-350
0764 812632-41
0180 2 12334
0800 5 23234213
+49 30 3432622-113
0179 1111111
Here is what I came up with: Regex
^(([+]{1}[1-9]{1}[0-9]{0,2}[ ]{1}([1-9]{1}[0-9]{1,4}){1}[ ]{1}([1-9]{1}[0-9]{2,6}){1}([ -][0-9]{1,5})?)|([0]{1}[1-9]{1}[0-9]{1,4}[ ]{1}[0-9]{1,8}([ -][0-9]{1,8})?)?)
Positives:
06429 1111
06901 306180
06429 231
0800 3301000
0179 1111111
0873 376461
03748 37682358
05444 347687-350
0764 812632-41
0180 2 12334
0800 5 23234213
+49 6429 1111
+49 39857 2530
+55 11 2666-0054
+300 11 2666-0054
+49 641 20106 0
+49 641 20106
+49 30 3432622-113
Negatives:
++49 157 184977
+300 11 0000-0000
(06442) 3933023
(02852) 5996-0
(042) 1818 87 9919
06442 / 3893023
06442 / 38 93 02 3
06442/3839023
042/ 88 17 890 0
+49 221 - 542194 79
+49 (221) - 542944 79
0 52 22 - 9 50 93 10
+49(0)121-79536 - 77
+49(0)2221-39938-113
+49 (0) 1739 906-44
+49 (173) 1799 806-44
0173173990644
0214154914479
01517953677
+491517953677
015777953677
02162 - 54 91 44 79
(02162) 54 91 44 79
saddsadasdasd
asdasd
asdasd asdasd asd
asdasd
kjn asohas asdoiasd
23434 234 234 23
323
23434 234----234
///// ----
// id8834 3493934 //
Hey i have a little enhancement for despecial‘s Regex:
(\(?([\d \-\)\–\+\(]+\/?){6,}\)?([ .\-–\/]?)([\d]+))
It filters numbers that have too high occurrencies of /

I got a different result when I retrained the sentiment model with Stanford CoreNLP to compare with the related paper's result

I downloaded stanford-corenlp-full-2015-12-09.
And I created a training model with the following command:
java -mx8g edu.stanford.nlp.sentiment.SentimentTraining -numHid 25 -trainPath train.txt -devPath dev.txt -train -model model.ser.gz
When I finished training, I found many files in my directory.
the model list
Then I used the evaluation tool from the package and I ran the code like this:
java -cp * edu.stanford.nlp.sentiment.Evaluate -model model-0024-79.82.ser.gz -treebank test.txt
The test.txt was from trainDevTestTrees_PTB.zip. This is the result about code:
F:\trainDevTestTrees_PTB\trees>java -cp * edu.stanford.nlp.sentiment.Evaluate -model model-0024-79.82.ser.gz -treebank test.txt
EVALUATION SUMMARY
Tested 82600 labels
65331 correct
17269 incorrect
0.790932 accuracy
Tested 2210 roots
890 correct
1320 incorrect
0.402715 accuracy
Label confusion matrix
Guess/Gold 0 1 2 3 4 Marg. (Guess)
0 551 340 87 32 6 1016
1 956 5348 2476 686 191 9657
2 354 2812 51386 3097 467 58116
3 146 744 2525 6804 1885 12104
4 1 11 74 379 1242 1707
Marg. (Gold) 2008 9255 56548 10998 3791
0 prec=0.54232, recall=0.2744, spec=0.99423, f1=0.36442
1 prec=0.5538, recall=0.57785, spec=0.94125, f1=0.56557
2 prec=0.8842, recall=0.90871, spec=0.74167, f1=0.89629
3 prec=0.56213, recall=0.61866, spec=0.92598, f1=0.58904
4 prec=0.72759, recall=0.32762, spec=0.9941, f1=0.4518
Root label confusion matrix
Guess/Gold 0 1 2 3 4 Marg. (Guess)
0 50 60 12 9 3 134
1 161 370 147 94 36 808
2 31 103 102 60 32 328
3 36 97 123 305 265 826
4 1 3 5 42 63 114
Marg. (Gold) 279 633 389 510 399
0 prec=0.37313, recall=0.17921, spec=0.9565, f1=0.24213
1 prec=0.45792, recall=0.58452, spec=0.72226, f1=0.51353
2 prec=0.31098, recall=0.26221, spec=0.87589, f1=0.28452
3 prec=0.36925, recall=0.59804, spec=0.69353, f1=0.45659
4 prec=0.55263, recall=0.15789, spec=0.97184, f1=0.24561
Approximate Negative label accuracy: 0.638817
Approximate Positive label accuracy: 0.697140
Combined approximate label accuracy: 0.671925
Approximate Negative root label accuracy: 0.702851
Approximate Positive root label accuracy: 0.742574
Combined approximate root label accuracy: 0.722680
The accuracy about fine-grained and positive/negative was quite different from the paper "Socher, R., Perelygin, A., Wu, J.Y., Chuang, J., Manning, C.D., Ng, A.Y. and Potts, C., 2013, October. Recursive deep models for semantic compositionality over a sentiment treebank. In Proceedings of the conference on empirical methods in natural language processing (EMNLP) (Vol. 1631, p. 1642)."
The paper states the accuracy about fine-grained and positive/negative is higher than mine.
The records in the paper
Were there any problems with my operation? Why was my result different from the paper?
The short answer is that the paper used a different system written in Matlab. The Java system does not match the paper. Though we do distribute the binary model we trained in Matlab with the English models jar. So you can RUN the binary model with Stanford CoreNLP, but you cannot TRAIN a binary model with similar performance with Stanford CoreNLP at this time.

Categories