Pregunta

¿Cuál es la mejor manera de transcribir el siguiente código Transact-SQL a Informix Dynamic Server (IDS) 9.40:

Objetivo: necesito los primeros 50 pedidos con sus respectivas líneas de pedido

select *
    from (select top 50 * from orders) a inner join lines b
            on a.idOrder = b.idOrder

Mi problema es con la subselección porque Informix no permite la PRIMERA opción en la subselección.

¿Alguna idea simple?

¿Fue útil?

Solución

La respuesta oficial sería 'Actualice desde IDS 9.40 ya que IBM ya no lo admite'. Es decir, IDS 9.40 no es una versión actual, y (idealmente) no debería usarse.

Solución para IDS 11.50

Usando IDS 11.50, puedo escribir:

SELECT *
    FROM (SELECT FIRST 10 * FROM elements) AS e
         INNER JOIN compound_component AS a
            ON e.symbol = a.element
         INNER JOIN compound AS c
            ON c.compound_id = a.compound_id
    ;

Esto es más o menos equivalente a su consulta. En consecuencia, si usa una versión actual de IDS, puede escribir la consulta usando casi la misma notación que en Transact-SQL (usando FIRST en lugar de TOP).

Solución para IDS 9.40

¿Qué puedes hacer en IDS 9.40? Disculpe un momento ... Tengo que ejecutar mi servidor IDS 9.40.xC7 (este fixpack fue lanzado en 2005; la versión original probablemente fue a fines de 2003) ...

Primer problema: IDS 9.40 no permite subconsultas en la cláusula FROM.

Segundo problema: IDS 9.40 no permite la notación 'PRIMERO n' en ninguno de estos contextos:

SELECT FIRST 10 * FROM elements INTO TEMP e;
INSERT INTO e SELECT FIRST 10 * FROM elements;

Tercer problema: IDS 9.40 no tiene un ROWNUM simple.

Entonces, para solucionar estos problemas, podemos escribir (usando una tabla temporal; lo eliminaremos más adelante):

SELECT e1.*
    FROM elements AS e1, elements AS e2
    WHERE e1.atomic_number >= e2.atomic_number
    GROUP BY e1.atomic_number, e1.symbol, e1.name, e1.atomic_weight, e1.stable
    HAVING COUNT(*) <= 10
    INTO TEMP e;

SELECT *
    FROM e INNER JOIN compound_component AS a
                   ON e.symbol = a.element
           INNER JOIN compound AS c
                   ON c.compound_id = a.compound_id;

Esto produce la misma respuesta que la consulta única en IDS 11.50. ¿Podemos evitar la mesa temporal? Sí, pero es más detallado:

SELECT e1.*, a.*, c.*
    FROM  elements AS e1, elements AS e2, compound_component AS a,
           compound AS c
    WHERE e1.atomic_number >= e2.atomic_number
      AND e1.symbol = a.element
      AND c.compound_id = a.compound_id
    GROUP BY e1.atomic_number, e1.symbol, e1.name, e1.atomic_weight,
             e1.stable, a.compound_id, a.element, a.seq_num,
             a.multiplicity, c.compound_id, c.name
    HAVING   COUNT(*) <= 10;

Aplicar eso a los pedidos originales más el ejemplo de líneas de pedido se deja como ejercicio para el lector.


Subconjunto relevante de esquema para 'Tabla de elementos':

-- See: http://www.webelements.com/ for elements.
-- See: http://ie.lbl.gov/education/isotopes.htm for isotopes.

CREATE TABLE elements
(
    atomic_number   INTEGER NOT NULL UNIQUE CONSTRAINT c1_elements
                    CHECK (atomic_number > 0 AND atomic_number < 120),
    symbol          CHAR(3) NOT NULL UNIQUE CONSTRAINT c2_elements,
    name            CHAR(20) NOT NULL UNIQUE CONSTRAINT c3_elements,
    atomic_weight   DECIMAL(8,4) NOT NULL,
    stable          CHAR(1) DEFAULT 'Y' NOT NULL
                    CHECK (stable IN ('Y', 'N'))
);

CREATE TABLE compound
(
    compound_id     SERIAL NOT NULL PRIMARY KEY,
    name            VARCHAR(100) NOT NULL UNIQUE
);

-- The sequence number is used to order the components within a compound.

CREATE TABLE compound_component
(
    compound_id     INTEGER REFERENCES compound,
    element         CHAR(3) NOT NULL REFERENCES elements(symbol),
    seq_num         SMALLINT DEFAULT 1 NOT NULL
                    CHECK (seq_num > 0 AND seq_num < 20),
    multiplicity    INTEGER NOT NULL
                    CHECK (multiplicity > 0 AND multiplicity < 20),
    PRIMARY KEY(compound_id, seq_num)
);

Salida (en mi base de datos de muestra):

 1 H   Hydrogen        1.0079 Y     1 H    1     2       1 water
 1 H   Hydrogen        1.0079 Y     3 H    2     4       3 methane
 1 H   Hydrogen        1.0079 Y     4 H    2     6       4 ethane
 1 H   Hydrogen        1.0079 Y     5 H    2     8       5 propane
 1 H   Hydrogen        1.0079 Y     6 H    2    10       6 butane
 1 H   Hydrogen        1.0079 Y    11 H    2     5      11 ethanol
 1 H   Hydrogen        1.0079 Y    11 H    4     1      11 ethanol
 6 C   Carbon         12.0110 Y     2 C    1     1       2 carbon dioxide
 6 C   Carbon         12.0110 Y     3 C    1     1       3 methane
 6 C   Carbon         12.0110 Y     4 C    1     2       4 ethane
 6 C   Carbon         12.0110 Y     5 C    1     3       5 propane
 6 C   Carbon         12.0110 Y     6 C    1     4       6 butane
 6 C   Carbon         12.0110 Y     7 C    1     1       7 carbon monoxide
 6 C   Carbon         12.0110 Y     9 C    2     1       9 magnesium carbonate
 6 C   Carbon         12.0110 Y    10 C    2     1      10 sodium bicarbonate
 6 C   Carbon         12.0110 Y    11 C    1     2      11 ethanol
 8 O   Oxygen         15.9990 Y     1 O    2     1       1 water
 8 O   Oxygen         15.9990 Y     2 O    2     2       2 carbon dioxide
 8 O   Oxygen         15.9990 Y     7 O    2     1       7 carbon monoxide
 8 O   Oxygen         15.9990 Y     9 O    3     3       9 magnesium carbonate
 8 O   Oxygen         15.9990 Y    10 O    3     3      10 sodium bicarbonate
 8 O   Oxygen         15.9990 Y    11 O    3     1      11 ethanol

Otros consejos

Si entiendo su pregunta, tiene un problema con "TOP". Intente usar una consulta TOP-N.

Por ejemplo:

select  *
  from  (SELECT  *
           FROM  foo
          where  foo_id=[number]
       order by  foo_id desc)
 where  rownum <= 50

Esto le dará los primeros cincuenta resultados (porque ordeno por desc en la subconsulta)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top