i need to get the most recurring vIndex in a lua table structured like this:
{{id=0, vIndex = 0},{id=34, vIndex = 1},...}
what's the best way to do so?
Loop over each element in a table and keep track on the number of occurrences in another table where each value of vIndex being a key. Then loop over the second table to find the element with the max value. This will be your most frequent vIndex.
Related
Both tables sorted by key KNO
LOOP AT lt_header INTO lwa_header.
LOOP AT lt_items INTO lwa_item
WHERE key = lwa_header-KNO
“……….
ENDLOOP.
ENDLOOP.
This would take more time to execute if number of entries in the table is huge. How should i modify code to improve the performance?
You should be able to improve the lookup in the second table by using a secondary table key. Such a key needs to be declared when you declare the table variable:
DATA lt_items TYPE TABLE OF whatever WITH NON-UNIQUE SORTED KEY k1 COMPONENTS key.
You can then use this key to accelerate lookups in that table from O(n) or O(log n) time complexity:
LOOP AT lt_header INTO lwa_header.
LOOP AT lt_items INTO lwa_item
USING KEY k1
WHERE key = lwa_header-KNO.
"...
ENDLOOP.
ENDLOOP.
When you can guarantee that the values in lt_items-key are always unique (there are no two lines with the same value for "key"), then you can even use a hashed key, which is even faster (constant time):
DATA lt_items TYPE TABLE OF whatever WITH UNIQUE HASHED KEY k1 COMPONENTS key.
LOOP AT lt_header INTO lwa_header.
READ TABLE lt_items INTO lwa_item
WITH TABLE KEY k1
COMPONENTS key = lwa_header-KNO.
IF sy-subrc = 0.
"...
ENDIF.
ENDLOOP.
You can use parallel cursor. It's a good technique for performance improvements in nested loops. For more information check this link.
Also field symbols are better for performance.
DATA lv_tabix TYPE sy-tabix.
SORT: lt_header BY kno,
lt_items BY kno.
LOOP AT lt_header ASSIGNING FIELD-SYMBOL(<lfs_header>).
READ TABLE lt_items TRANSPORTING NO FIELDS
WITH KEY kno = <lfs_header>-kno
BINARY SEARCH.
lv_tabix = sy-tabix.
LOOP AT lt_items FROM lv_tabix ASSIGNING FIELD-SYMBOL(<lfs_item>).
IF <lfs_header>-kno <> <lfs_item>-kno.
EXIT.
ENDIF.
"Your logic should be here..
ENDLOOP.
ENDLOOP.
I have an oracle table. Table's DDL is (not have the primary key)
create table CLIENT_ACCOUNT
(
CLIENT_ID VARCHAR2(18) default ' ' not null,
ACCOUNT_ID VARCHAR2(18) default ' ' not null,
......
)
create unique index UK_ACCOUNT
on CLIENT_ACCOUNT (CLIENT_ID, ACCOUNT_ID)
Then, the data's scale is very huge, maybe 100M records. I want to traverse this whole table's data with batch.
Now, I use the table's index to batch traverse. But I have some oracle grammar problems.
# I want to use this SQL, but grammar error.
# try to use b-tree's index to locate start position, but not work
select * from CLIENT_ACCOUNT
WHERE (CLIENT_ID, ACCOUNT_ID) > (1,2)
AND ROWNUM < 1000
ORDER BY CLIENT_ID, ACCOUNT_ID
Has the fastest way to batch touch table data?
Wild guess:
select * from CLIENT_ACCOUNT
WHERE CLIENT_ID > '1'
and ACCOUNT_ID > '2'
AND ROWNUM < 1000;
It would at least compile, although whether it correctly implements your business logic is a different matter. Note that I have cast your filter criteria to strings. This is because your columns have a string datatype and you are defaulting them to spaces, so there's a high probability those columns contain non-numeric values.
If this doesn't solve your problem, please edit your question with more details; sample input data and expected output is always helpful in these situations.
Your data model seems odd.
Your columns are defined as varchar2. So why is your criteria numeric?
Also, why do you default the key columns to space? It would be better to leave unpopulated values as null. (To be clear, NULL is not a good thing in an indexed column, it's just better than a space.)
I have a question for all of you. I'm quite new in SQL and searched for more than 2 hours and didn't find exactly what I need.
I'm having a table in SQL named Courses. Here is the constructor:
CREATE TABLE Courses
(sign VARCHAR2(6) NOT NULL,
title VARCHAR(50) NOT NULL,
credits INTEGER NOT NULL,
CONSTRAINT PrimaryKeyCourses PRIMARY KEY (sign)
);
I have to add a new column, which I did with :
ALTER TABLE Courses ADD frequency INTEGER;
I want to create a trigger which will increment every time a new courses is added.
I tried to do this :
CREATE TRIGGER fq
AFTER INSERT ON Courses
FOR EACH ROW
UPDATE frequency SET frequency = frequency + 1;
But it doesn't seems to work properly :( I don't know what to do.
No need to use an UPDATE statement, use a SELECT statement with max(value)+1. And to be able to change a :new. value, need to convert trigger to BEFORE type.
So, you can use the one as below
CREATE OR REPLACE TRIGGER fq
BEFORE INSERT ON Courses
FOR EACH ROW
DECLARE
BEGIN
select nvl(max(frequency),0)+1
into :new.frequency
from Courses;
END;
Of course you need a commit after a DML statement, I think it's better to include only one commit outside of this trigger after INSERT statement applied on Courses table, because of providing transaction integrity rule.
P.S. I know you're restricted to use a trigger, but Using a sequence for the value of column frequency is a better, practical alternative as #nikhil sugandh suggested. In this case a trigger is not needed. If you're using DB version 12c, you can add that sequence as default for the column frequency as frequency INTEGER GENERATED ALWAYS AS IDENTITY during the table creation.
use sequence :
CREATE SEQUENCE Courses_frequency
MINVALUE 1
MAXVALUE 999999999999999999999999999
START WITH 1
INCREMENT BY 1
CACHE 20;
and do insert like:
INSERT INTO Courses
(sign,title,credits,frequency)
VALUES
(value1,value2,value3,Courses_frequency.NEXTVAL);
I have to create a trigger for a table with many columns and I want to now if is any possibility to avoid using the name of the column after :new and :old. Instead of specifically use the column name I want to use the element from collection with column names of target table (the table on which the trigger is set).
The line 25 is that with the binding error:
DBMS_OUTPUT.PUT_LINE('Updating customer id'||col_name(i)||to_char(:new.col_name(i)));
Bellow you can see my trigger:
CREATE OR REPLACE TRIGGER TEST_TRG BEFORE
INSERT OR
UPDATE ON ITEMS REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW DECLARE TYPE col_list IS TABLE OF VARCHAR2(60);
col_name col_list := col_list();
total INTEGER;
counter INTEGER :=0;
BEGIN
SELECT COUNT(*)
INTO total
FROM user_tab_columns
WHERE table_name = 'ITEMS';
FOR rec IN
(SELECT column_name FROM user_tab_columns WHERE table_name = 'ITEMS'
)
LOOP
col_name.extend;
counter :=counter+1;
col_name(counter) := rec.column_name;
dbms_output.put_line(col_name(counter));
END LOOP;
dbms_output.put_line(TO_CHAR(total));
FOR i IN 1 .. col_name.count
LOOP
IF UPDATING(col_name(i)) THEN
DBMS_OUTPUT.PUT_LINE('Updating customer id'||col_name(i)||to_char(:new.col_name(i)));
END IF;
END LOOP;
END;
Sincerely,
After digging more I have found that is not possible to dynamically reference the :new.column_name or :old.column_name values in a trigger. Due to this I will use my code only to INSERT (it does not have an old value :-() and I will do some code in java to generate UPDATE statements.
I must refine my previous answer based on what has been said by Justin Cave and also my findings. We can create a dynamic list of values triggered by INSERTING and UPDATING, based on referencing clause (old and new). For example I have created 2 collections of type nested table with varchars. One collection will contain all column tabs, as strings, that I will use for auditing and another collection will contains values for that columns with binding reference (ex. :new.). After INSERTING predicate I have created a index by collection (an associative array) of strings with ID taken from list of strings with column tab name and the value taken from the list of values for that columns referenced by new. Due to the index by collection you have a full working dynamic list at your disposal. Good luck :-)
Using Oracle DB
Trying to create logic where when inserting a new row the logic checks if there is an existing numerical value. If there is a value then the logic would perform a max(value)+1. If there is no value then INSERT '1'.
I would suggest that you use a sequence instead of looking for the max value + 1.
A sequence would take care of the incrementing for you. http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_6015.htm
Example:
CREATE SEQUENCE MY_SEQ START WITH 1 INCREMENT BY 1;
Insert like
INSERT INTO MY_TABLE (ID, WIDGET) VALUES (NEXTVAL FOR MY_SEQ, 'asdf');