1

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.

Jagger
  • 10,350
  • 9
  • 51
  • 93

0 Answers0