Compare two records and highlight the differences - oracle

I have a oracle apex report which fetches two rows every time.
I want to highlight all the columns where data is different in two rows.
So when user looks at the comparison report he don't have to go through all the columns to identify where data has been changed.
I have tried to look at the apex features and some javascript code but was unable to do so reliably.
You can have a look at sample report here:
https://apex.oracle.com/pls/apex/f?p=128616:8:109311280077805:::::
go to page "help me with comparison"
I want to highlight the benefit name column as data is different in benefit name column.

if your table has id "test" you can try call this function on page load compareRows(document.getElementById('test'));
the function body:
function compareRows(table) {
var row1,row2, rows = table.rows;
var cell1,cell2;
var rowText;
row1=rows[1];
row2=rows[2];
cell1=row1.cells;
cell2=row2.cells;
for (var i=0; i<cell1.length; i++) {
if(cell1[i].textContent != cell2[i].textContent){
cell1[i].style.backgroundColor = "red";
cell2[i].style.backgroundColor = "red";
}
}
}

You can use the analytic function "LAG" to reference the previous row in your resultset.
So one possible solution is to (1) select the value of the current row and the value of the previous row, (2) compare the 2 columns and set a flag, only in row 2 because that is where you want to highlight, (3) use highlighting in apex to indicate which columns have different values. See example sql below for an example.
-- create tables
create table so_dummy_data (
id number generated by default on null as identity
constraint so_dummy_data_id_pk primary key,
name varchar2(100) not null,
email varchar2(100) not null
)
;
-- load data
insert into so_dummy_data (
id,
name,
email
) values (
1,
'John Doe',
'john.doe#mail.com'
);
insert into so_dummy_data (
id,
name,
email
) values (
2,
'John Doe',
'john.x.doe#mail.com'
);
commit;
WITH old_and_new AS
(SELECT
id,
name,
LAG(name,1)OVER(
ORDER BY
name
)AS new_name,
email,
LAG(email,1)OVER(
ORDER BY
1
)AS new_email,
row_number() over (order by 1) rn
FROM
so_dummy_data
)
SELECT
name,
CASE
WHEN rn = 1 THEN 'N'
WHEN name = new_name THEN
'N'
ELSE
'Y'
END AS name_changed,
email,
CASE
WHEN rn = 1 THEN 'N'
WHEN email = new_email THEN
'N'
ELSE
'Y'
END AS email_changed
FROM
old_and_new;

Related

Insert into table two and update table two for BigQuery in one query

I am using StandardSQL in BigQuery. I am writing a scheduled query which inserts records into table (2). Now, given that it's sceduled, I am trying to figure out how to update records in table (2) from the sceduled query, which is always inserting records into table (2).
In particular, when there is a record in table (2) but not generated by my query then I want to update table (2) and a boolean column to No.
Below is my query, where in the query would I add the update logic for table (2)?
INSERT INTO record (airport_name, icao_address, arrival, flight_number, origin_airport_icao, destination_airport_icao)
WITH
planes_stopped_in_airport AS (
SELECT
p.IATA_airport_code,
p.airport_name,
p.airport_ISO_country_code,
p.ICAO_airport_code,
timestamp,
a.icao_address,
a.latitude,
a.longitude,
a.altitude_baro,
a.speed,
heading,
callsign,
source,
a.collection_type,
vertical_rate,
squawk_code,
icao_actype,
flight_number,
origin_airport_icao,
destination_airport_icao,
scheduled_departure_time_utc,
scheduled_arrival_time_utc,
estimated_arrival_time_utc,
tail_number,
ingestion_time
FROM
`updates` a
JOIN
Polygons p
ON
1 = 1
WHERE
a.timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 20 MINUTE) and a.timestamp <= CURRENT_TIMESTAMP()
AND ( latitude IS NULL
AND longitude IS NULL
AND callsign IS NULL
AND speed IS NULL
AND heading IS NULL
AND altitude_baro IS NULL) IS FALSE
AND ST_DWithin( ST_GeogFromText( polygon ),
ST_GeogPoint(a.longitude,
a.latitude),
10)
AND a.collection_type = '1' -- and speed < 50
AND (origin_airport_icao IS NULL
AND destination_airport_icao IS NULL) IS FALSE )
SELECT
p.airport_name,
icao_address,
MIN(timestamp) AS Arrival,
flight_number,
origin_airport_icao,
destination_airport_icao
FROM
planes_stopped_in_airport p
WHERE
flight_number NOT IN (SELECT Distinct flight_number
FROM `table(2)`
)
GROUP BY
icao_address,
p.airport_name,
flight_number,
origin_airport_icao,
destination_airport_icao
HAVING
flight_number IS NOT NULL
ORDER BY
airport_name,
arrival
You can probably do it with MERGE statement, see details in https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement.
If I understood your requirements correctly, you need something like
MERGE dataset.Destination T
USING (SELECT * ...) S
ON T.key = S.key
WHEN MATCHED THEN
UPDATE SET T.foo = S.foo, T.bool_flag = FALSE
WHEN NOT MATCHED THEN
INSERT ...

update on select ORA-01732

I get on oracle-server ORA-01732.
There are any other issues with this ORA, but it does not help me on my situation.
I select typicaly some data from two tables and i group these something like this:
SELECT SUM (LG_ALL.HOURS) AS hour_sum,
TO_CHAR (LG_ALL.WORK_DATE, 'YYYY.MM') AS singel_month,
LG_ALL.EXPORTED
FROM USER usr,
USER_ALLWC LG_ALL,
WHERE usr.user_id = LG_ALL.user_id
AND LG_ALL.EXPORTED = 'N'
GROUP BY
TO_CHAR (LG_ALL.WORK_DATE, 'YYYY.MM'),
LG_ALL.EXPORTED
ORDER BY usr.LOGNAME DESC
At next step, I have to set on table USER_ALLWC:
LG_ALL.EXPORTED = 'Y'
Because of this, i wrap this into update-statement like
updates-based-on-queries => Inline View Method:
UPDATE ( SELECT SUM (LG_ALL.HOURS) AS hour_sum,
TO_CHAR (LG_ALL.WORK_DATE, 'YYYY.MM') AS singel_month,
LG_ALL.EXPORTED
FROM USER usr,
USER_ALLWC LG_ALL,
WHERE usr.user_id = LG_ALL.user_id
AND LG_ALL.EXPORTED = 'N'
GROUP BY
TO_CHAR (LG_ALL.WORK_DATE, 'YYYY.MM'),
LG_ALL.EXPORTED
ORDER BY usr.LOGNAME DESC ) allg
SET allg.EXPORTED = 'Y';
Sadly I get ORA-01732.
Can anyone explain, when I can update on select-statement and how can I fix it?
From Oracle SQL Language Reference:
The view must not contain any of the following constructs:
A set operator
A DISTINCT operator
An aggregate or analytic function
...
Try simplifying it - the sum, group by etc. add no value anyway:
UPDATE ( SELECT LG_ALL.EXPORTED
FROM USER usr,
USER_ALLWC LG_ALL,
WHERE usr.user_id = LG_ALL.user_id
AND LG_ALL.EXPORTED = 'N'
) allg
SET allg.EXPORTED = 'Y';
As long as there is a foreign key from USER_ALLWC to USER this should work.
In fact, assuming there is such a foreign key the whole statement is equivalent to:
UPDATE USER_ALLWC
SET EXPORTED = 'Y'
WHERE EXPORTED = 'N';

ORACLE APEX PLSQL - LOV LIST, how to have static value as last value in list?

I have a lov list with an sql query to dynaically fill it in depending on other fields, however, i'd like the last value in the list to be 'Other' no matter what the sql query brings back.
select EMP_NAME as d,
EMP_NAME as r
from EMP
WHERE EMP_NAME = :P09_CAT
order by 1
There is declarative functionality built in for this common purpose. See just before 13.2.3 http://docs.oracle.com/database/apex-5.1/HTMDB/managing-page-level-items-in-page-designer.htm#HTMDB29715
Check the "List of Values" set of attributes for the item, specifically "Display null value", "Null Display Value".
Ensure the first is checked, and the latter says 'Other'.
Alternatively, if you want specific data in your LOV you can add a UNION ALL, e.g.:
select d, r from (
select EMP_NAME as d,
EMP_NAME as r,
row_number() over (order by emp_name) s
from EMP
WHERE EMP_NAME = :P09_CAT
union all
select 'Other','Other',9999999999 from dual
) order by s
Create event on page load and use this javascript:
var x = document.getElementById("P605_NEW");
var option = document.createElement("option");
option.text = "Other";
x.add(option);
Where my select list is P605_NEW

Oracle-update multiple row value where the the id column equals specific values

I am new in oracle and I want to update multiple row value where the column id = 1 , 2.
I tried this :
update Tester
set employee_phone_number = ( 0789456123,0789456321)
where employee_id in (1,2);
but it gives me "missing right parenthesis"
any help please and thanks in advance.
Another approach:
merge into
tester
using (
select 1 id,'0123456785' employee_phone_number from dual union all
select 2 id,'0123456786' employee_phone_number from dual) new_values
on (
tester.id = new_values.id)
when matched then update
set employee_phone_number = new_values.employee_phone_number;
More words, but allows the values to be specified in only one place and extends to allow inserts where the id does not already exist.
http://sqlfiddle.com/#!4/8fc86/3
Try this instead:
update Tester
set employee_phone_number = CASE WHEN employee_id = 1 THEN 0789456123
WHEN employee_id = 2 THEN 0789456321
END
where employee_id in (1,2);

How to count the number of elements in all Oracle varrays from table?

I have a table like this:
CREATE TABLE spatial_data (
id NUMBER PRIMARY KEY,
geometry SDO_GEOMETRY);
SDO_GEOMETRY has a field sdo_ordinates with the following type:
TYPE SDO_ORDINATE_ARRAY AS VARRAY(1048576) OF NUMBER
I can get the number of points for specified object:
select count(*)
from table(
select s.geometry.sdo_ordinates
from spatial_data s
where s.id = 12345
);
How can I get count for several objects? It's not possible to use
where s.id in (1, 2, 3, 4, 5)
And I really care about performance. Maybe PL/SQL would be the right choice?
I think that you can do it with one query:
select s.id, count(*)
from spatial_data s, table(s.geometry.sdo_ordinates)
group by s.id
or you can write a plsql simple function that returns the count attribute of the SDO_ORDINATE_ARRAY VARRAY:
create or replace function get_count(ar in SDO_ORDINATE_ARRAY) return number is
begin
return ar.count;
end get_count;
or even nicer add a member function to SDO_GEOMETRY TYPE which return the count attribute

Resources