Teradata, Update single row if target has duplicate rows - teradata

I want to update single row in target table if target has two duplicate rows.
target table
Employee_Id Join_date Status Eartned_points used_vocher_cnt
123 02/01/2021 A 50 null
123 02/01/2021 A 40 null
source table
Employee_Id Join_date Status used_vocher_cnt
123 02/01/2021 A 4
There are two rows in target table and only one row has to be update with used_vocher_cnt 4
(either of the row) i.e total used vochers used by employee is 4.
UPDATE TGT
FROM (
SELECT EMPLOYEE_ID,
JOIN_DATE,
STATUS,
USED_VOCHER_CNT
FROM TARGET_TABLE
QUALIFY ROW_NUMBER() OVER( PARTITION BY Employee_id,Join_date,Status ORDER BY Eartned_points DESC)=1
)TGT,
SOURCE_TABLE SRC
SET Used_vocher_cnt=SRC.used_vocher_cnt
WHERE SRC.Join_date=TGT.Join_date
AND SRC.EMPLOYEE_ID=TGT.EMPLOYEE_ID
AND SRC.Status=TGT.Status;
Error: derived table not allowed for update

Related

SQLite UPDATE now working or I have done wrong

Current table questions:
rowid: 1 | 2 | 3 | 4 | 5
id: 3 | 4 | 7 | 9 | 10
Trying to achieve the following:
rowid: 1 | 2 | 3 | 4 | 5
id: 1 | 2 | 3 | 4 | 5
I have tried many different variations of SQL without success, this is the latest I am testing:
UPDATE questions SET id = rowid;
Can someone please suggest how I solve this as I have googled and cannot find the solution?
I don't believe that your question completely encompasses all aspects of the issue.
In theory to have a table (the before table) where SELECT rowid, id results in
rowid: 1 | 2 | 3 | 4 | 5
id: 3 | 4 | 7 | 9 | 10
The id column must not be an alias of the rowid column (otherwise the values would be identical)
However, if the id column is an alias of the rowid column, the both columns would be the same so the before table above would not be as above.
As an example using :-
--<<<<<<<<<< WORKS >>>>>>>>>>
-- as ID is not an alias of the rowid column update changes id column
DROP TABLE IF EXISTS questionsv3;
CREATE TABLE IF NOT EXISTS questionsv3 (ID INTEGER);
INSERT INTO questionsv3 VALUES (3),(4),(7),(9),(10);
SELECT rowid, id FROM questionsv3;
UPDATE questionsv3 SET id = rowid;
SELECT rowid, id FROM questionsv3;
results in the expected result as per :-
First Select (before update) :-
Second Select (after update)
Other potential causes
rowid is not in fact the rowid as per SQLITE, but a conceptual idea that it should be 1,2,3 ...... (in which case using VACUUM, if there is no alias to the rowid, may result in the desired re-numbering of the rowid column, which if followed by the update may then result in the id being re-sequenced).
That the update is done within a transaction that hasn't been committed and is rolled back.
You may wish to consider the following permutations of different table creations (see comments) :-
-- as ID is an alias of rowid, then rowid is set according to ID so update does nothing
DROP TABLE IF EXISTS questionsv1;
CREATE TABLE IF NOT EXISTS questionsv1 (ID INTEGER PRIMARY KEY);
INSERT INTO questionsv1 VALUES (3),(4),(7),(9),(10);
SELECT rowid, id FROM questionsv1;
UPDATE questionsv1 SET id = rowid;
SELECT rowid, id FROM questionsv1;
-- as ID is an alias of the rowid column, then rowid is set according to the ID so update does nothing
DROP TABLE IF EXISTS questionsv2;
CREATE TABLE IF NOT EXISTS questionsv2 (ID INTEGER PRIMARY KEY AUTOINCREMENT);
INSERT INTO questionsv2 VALUES (3),(4),(7),(9),(10);
SELECT rowid, id FROM questionsv2;
UPDATE questionsv2 SET id = rowid;
SELECT rowid, id FROM questionsv2;
--<<<<<<<<<< WORKS >>>>>>>>>>
-- as ID is not an alias of the rowid column update changes id column
DROP TABLE IF EXISTS questionsv3;
CREATE TABLE IF NOT EXISTS questionsv3 (ID INTEGER);
INSERT INTO questionsv3 VALUES (3),(4),(7),(9),(10);
SELECT rowid, id FROM questionsv3;
UPDATE questionsv3 SET id = rowid;
SELECT rowid, id FROM questionsv3;
--<<<<<<<<<< WORKS >>>>>>>>>>
-- as ID is not an alias of rowid the ID column is updated accordingly
DROP TABLE IF EXISTS questionsv4;
CREATE TABLE IF NOT EXISTS questionsv4 (ID TEXT PRIMARY KEY); -- not an alias of rowid
INSERT INTO questionsv4 VALUES (3),(4),(7),(9),(10);
SELECT rowid, id FROM questionsv4;
UPDATE questionsv4 SET id = rowid;
SELECT rowid, id FROM questionsv4;
--<<<<<<<<<< FAILS >>>>>>>>>>
DROP TABLE IF EXISTS questionsv13;
CREATE TABLE IF NOT EXISTS questionsv13 (ID INTEGER PRIMARY KEY) WITHOUT ROWID;
INSERT INTO questionsv13 VALUES (3),(4),(7),(9),(10);
SELECT id FROM questionsv13;
UPDATE questionsv13 SET id = rowid; -- would fail no such column
SELECT id FROM questionsv13;

Teradata - OLAP Functions - filter rows

I'm wondering if I can use an OLAP Function to filter irrelevant rows like this:
If I have one matching value (the fourth fields) all the rows with the same key ( the first 3 fields) must not be displayed
In this example, the matching value would be 'C':
Entities product ID Solde
997 0050 123 D
997 0050 123 D
997 0050 123 C
899 0124 125 D
899 0124 125 D
So here My key is composed by entities/product/ID, regarding the value of "Solde" I need to display or not.
Here the the undesired value is Solde = C.
In this example only the last row should be diplayed, because the key 899/0124/125 has only rows with solde = 'D'
The key 997/0050/123 has one row with solde = 'C' so I don't want to display it
Thanks in advance for your helping
Christophe
Updated answer
The more traditional way to solve this is to first select the Entities/Product/ID records that you DON'T want.
SELECT Entities, Product, ID FROM table WHERE Solde<>'D';
Use that result in a subquery in your WHERE clause to exclude those:
SELECT DISTINCT Entities, Product, ID, Solde
FROM table
WHERE (Entities, Product, ID) NOT IN ( SELECT Entities, Product, ID FROM table WHERE Solde<>'D');
Alternatively using a HAVING clause and aggregating
SELECT Entities, Product, ID
FROM table
COUNT(*) = SUM(CASE WHEN Solde = 'D' THEN 1 ELSE 0 END)
GROUP BY 1,2,3
I guess you are looking for answer as the below:
SELECT Solde
FROM yourtable
QUALIFY COUNT(*) OVER (PARTITION BY Entities, Product, ID, Solde) = 1;

How to establish many-many relationship in a oracle database?

I'm intended to develop a database model for my department. I found it difficult to establish the relationship between student, courses and staffs considering that any number of students can elect any number of courses and any number of staffs can handle any number of courses. How will I be able to represent this data in an oracle database?
What did you manage to do so far? What kind of difficulties did you meet?
Anyway: here's a suggestion, see whether it helps. An example is based on your STUDENT and COURSES tables. Idea is to include additional "cross" table which maps courses and students, i.e. contains columns that make primary keys of both tables, they are constrained by foreign key constraints and both of them make the primary key of the new, cross table.
Here's the code:
Create tables:
SQL> -- Students
SQL> create table t_student
2 (id_student number constraint pk_stu primary key,
3 student_name varchar2(20) not null
4 );
Table created.
SQL> -- Courses
SQL> create table t_course
2 (id_course number constraint pk_cou primary key,
3 course_name varchar2(20) not null
4 );
Table created.
SQL> -- Additional "cross" table
SQL> create table t_stu_x_cou
2 (id_student number constraint fk_sxc_stu
3 references t_student (id_student),
4 id_course number constraint fk_sxc_cou
5 references t_course (id_course),
6 constraint pk_sxc primary key (id_student, id_course)
7 );
Table created.
Insert sample data:
SQL> insert into t_student (id_student, student_name)
2 select 1, 'Little' from dual union
3 select 2, 'Foot' from dual;
2 rows created.
SQL> insert into t_course (id_course, course_name)
2 select 100, 'Mathematics' from dual union
3 select 200, 'Physics' from dual union
4 select 300, 'Chemistry' from dual;
3 rows created.
SQL> -- Mapping students and courses:
SQL> -- - student 1 takes 2 courses (100 and 300)
SQL> -- - student 2 takes 3 courses (100, 200 and 300)
SQL> insert into t_stu_x_cou (id_student, id_course)
2 select 1, 100 from dual union
3 select 1, 300 from dual union
4 --
5 select 2, 100 from dual union
6 select 2, 200 from dual union
7 select 2, 300 from dual;
5 rows created.
Select that shows courses taken by student 1:
SQL> select s.student_name, c.course_name
2 from t_stu_x_cou x
3 join t_student s on s.id_student = x.id_student
4 join t_course c on c.id_course = x.id_course
5 where s.id_student = 1;
STUDENT_NAME COURSE_NAME
-------------------- --------------------
Little Mathematics
Little Chemistry
SQL>
Now, try to add the STAFF table yourself, using the same principle (you'd add a new "cross" table between STAFF and COURSES).

Updating Fields sequentially based on conditions

I have this current example data set
NEW_ID Name OLD_ID New_Name
123 Hello XYZ
124 How XYZ
125 Are XYZ
126 My ABC
127 Name ABC
128 Is ABC
129 Alex ABC
My objective is to amend the Name field to a new naming convention to be stored in New_Name- ie Hello_Part_1, How_Part_2, Are_Part_3 where all these records share an OLD_ID - in this case XYZ. Similarly, with My_Part_1, Name_Part_2, Is_Part_3, Alex_Part_4 etc with IDs that equal ABC.
I'm using SQL Lite with an Import of .CSV File.
The naming convention is as follows - NAME_PART_X where X increments on the number of records within that 'Group' of OLD_IDs.
SQL does not work sequentially; you have to express the operation independently for each row.
The number you want is the count of rows with the same old ID that also have a new ID that is the same or smaller as the new ID of the current row.
This can be computed with a correlated subquery:
UPDATE MyTable
SET New_Name = Name || '_Part_' ||
(SELECT COUNT(*)
FROM MyTable AS T2
WHERE T2.OLD_ID = MyTable.OLD_ID
AND T2.NEW_ID <= MyTable.NEW_ID);

How to SELECT values not found in a table?

I would like to determine particular IDs that are not present in a table.
For example, I have the IDs 1, 2 and 3 and want to know if they exist in the table.
Essentially this would boil down to:
SELECT id FROM (
SELECT 1 AS id
UNION
SELECT 2 AS id
UNION
SELECT 3 AS id
)
WHERE
NOT EXISTS (SELECT * FROM table WHERE table.id = id)
Suppose table had the IDs 1 and 4, then this would yield 2 and 3.
Are there more elegant / concise / faster ways to get those IDs in SQLite ?
The compound SELECT operator EXCEPT allows you to do something similar to NOT EXISTS:
SELECT 1 AS id UNION ALL
SELECT 2 UNION ALL
SELECT 3
EXCEPT
SELECT id FROM MyTable
Beginning with SQLite 3.8.3, you can use VALUES everywhere you could use SELECT, but this is just a different syntax:
VALUES (1),
(2),
(3)
EXCEPT
SELECT id FROM MyTable

Resources