I have the following tables (those tables contain many records but for sake of this example I reduced the contents only to the records I want to operate on).
Products
product_id | product_name
------------+--------------
1 | PRODUCT
Contracts
contract_id | version | status | product_id
-------------+---------+--------+------------
2 | 1 | 30 | 1
2 | 2 | 30 | 1
2 | 3 | 30 | 1
2 | 4 | 30 | 1
2 | 5 | 30 | 1
2 | 6 | 30 | 1
People
id | guid
----+------
3 | 123
9 | 456
Limits
id | type
----+------
4 | 12
5 | 14
Link_table
link_id | version | contract_id | object_type | function | obj_id
---------+---------+-------------+-------------+----------+--------
6 | 1 | 2 | XADL | ADLTYP | 4
7 | 2 | 2 | XADL | ADLTYP | 5
8 | 2 | 2 | BCBP | BCA010 | 123
10 | 3 | 2 | BCBP | BCA010 | 456
Here is the DDL for the aforementioned tables...
CREATE TABLE products (
product_id integer PRIMARY KEY,
product_name varchar(10) NOT NULL
);
CREATE TABLE contracts (
contract_id integer,
version integer,
status varchar(2) NOT NULL,
product_id integer NOT NULL REFERENCES products(product_id),
PRIMARY KEY (contract_id, version)
);
CREATE TABLE link_table (
link_id integer,
version integer,
contract_id integer NOT NULL,
object_type varchar(4) NOT NULL,
function varchar(6) NOT NULL,
obj_id integer NOT NULL,
PRIMARY KEY(link_id, version)
);
CREATE TABLE people (
id integer PRIMARY KEY,
guid integer,
CONSTRAINT person_guid UNIQUE(guid)
);
CREATE TABLE limits (
id integer PRIMARY KEY,
type varchar(2) NOT NULL
);
Now... My task is to select the latest version of the value for field type
in limits
table for the latest version of the value id
in the people
table. The table link_table
decides what the latest version is. This data need to be provided with fields contract_id
, status
, product_name
.
I tried with the following query, unfortunately I receive two rows when I am supposed to receive only one with the latest value.
SELECT c.contract_id, status, product_name, type
FROM
contracts AS c
INNER JOIN
products AS p
ON c.product_id = p.product_id
INNER JOIN
link_table AS per
ON c.contract_id = per.contract_id
INNER JOIN
link_table AS ll
ON per.contract_id = ll.contract_id
INNER JOIN
people AS peop
ON per.obj_id = peop.guid
INNER JOIN
limits AS lim
ON ll.obj_id = lim.id
WHERE
peop.id = 3
AND per.object_type = 'BCBP'
AND per.function = 'BCA010'
AND ll.object_type = 'XADL'
AND ll.function = 'ADLTYP'
AND ll.version IN ( SELECT max(version) FROM link_table WHERE link_id = ll.link_id)
AND per.version IN ( SELECT max(version) FROM link_table WHERE link_id = per.link_id)
AND c.version IN ( SELECT max(version) FROM contracts WHERE contract_id = c.contract_id );
The result I expect is
contract_id | status | product_name | type
-------------+--------+--------------+------
2 | 30 | PRODUCT | 12
However the actual outcome is
contract_id | status | product_name | type
-------------+--------+--------------+------
2 | 30 | PRODUCT | 12
2 | 30 | PRODUCT | 14
I have been struggling with this for over a day now. Could anyone tell me what I am doing wrong? This example is done with PostgreSQL but the real problem needs to be solved with ABAP's OpenSQL so I cannot use UNION
.
Here is some SQL to populate the tables.
INSERT INTO products VALUES (1, 'PRODUCT');
INSERT INTO contracts VALUES (2, 1, '30', 1);
INSERT INTO contracts VALUES (2, 2, '30', 1);
INSERT INTO contracts VALUES (2, 3, '30', 1);
INSERT INTO contracts VALUES (2, 4, '30', 1);
INSERT INTO contracts VALUES (2, 5, '30', 1);
INSERT INTO contracts VALUES (2, 6, '30', 1);
INSERT INTO people VALUES (3, 123);
INSERT INTO people VALUES (9, 456);
INSERT INTO limits VALUES (4, '12');
INSERT INTO limits VALUES (5, '14');
INSERT INTO link_table VALUES (6, 1, 2, 'XADL', 'ADLTYP', 4);
INSERT INTO link_table VALUES (7, 2, 2, 'XADL', 'ADLTYP', 5);
INSERT INTO link_table VALUES (8, 2, 2, 'BCBP', 'BCA010', 123);
INSERT INTO link_table VALUES (10, 3, 2, 'BCBP', 'BCA010', 456);
EDIT
Looks like if the following records in table_link
link_id | version | contract_id | object_type | function | obj_id
---------+---------+-------------+-------------+----------+--------
6 | 1 | 2 | XADL | ADLTYP | 4
7 | 2 | 2 | XADL | ADLTYP | 5
were defined with the same link_id
then my query would return exactly what I want.
link_id | version | contract_id | object_type | function | obj_id
---------+---------+-------------+-------------+----------+--------
7 | 1 | 2 | XADL | ADLTYP | 4
7 | 2 | 2 | XADL | ADLTYP | 5
Unfortunately link_id
is generated each time new in production even if there is a version
in the composite key... Looks like I have to find another way or look for other fields in the link table that would help me.