带有 FIRST 选项的 Informix 子查询

Posted

技术标签:

【中文标题】带有 FIRST 选项的 Informix 子查询【英文标题】:Informix subqueries with FIRST option 【发布时间】:2009-06-23 16:34:24 【问题描述】:

将以下 Transact-SQL 代码转录到 Informix Dynamic Server (IDS) 9.40 的最佳方式是什么:

目标:我需要前 50 个订单及其各自的订单行

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

我的问题在于子选择,因为 Informix 不允许在子选择中使用 FIRST 选项。

有什么简单的想法吗?

【问题讨论】:

【参考方案1】:

官方回答是“请从 IDS 9.40 升级,因为 IBM 不再支持它”。也就是说,IDS 9.40 不是当前版本 - 应该(理想情况下)不使用。

IDS 11.50 解决方案

使用 IDS 11.50,我可以编写:

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
    ;

这或多或少等同于您的查询。因此,如果您使用当前版本的 IDS,您可以使用与 Transact-SQL 中几乎相同的表示法编写查询(使用 FIRST 代替 TOP)。

IDS 9.40 解决方案

您可以在 IDS 9.40 中做什么?打扰一下...我必须启动我的 IDS 9.40.xC7 服务器(此修订包于 2005 年发布;最初的版本可能在 2003 年末)...

第一个问题 - IDS 9.40 不允许 FROM 子句中的子查询。

第二个问题 - IDS 9.40 不允许在以下任何一种情况下使用“FIRST n”表示法:

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

第三个问题 - IDS 9.40 没有简单的 ROWNUM。

因此,为了解决这些问题,我们可以编写(使用临时表 - 我们稍后会删除它):

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;

这会产生与 IDS 11.50 中的单个查询相同的答案。我们可以避免临时表吗?是的,但它更冗长:

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;

将其应用于原始订单和订单行示例留作读者练习。


“元素表”的相关架构子集:

-- 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)
);

输出(在我的示例数据库上):

 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

【讨论】:

请注意:“IDS 9.40 不允许 FROM 子句中的子查询。”虽然这在技术上是正确的,但您可以使用SELECT * FROM table(multiset( SELECT * FROM xxx... )) - 这与真正的 ANSI 派生表基本相同。您可以在内部 SELECT 中执行的操作有一些限制,但大多数情况下它是有效的。 @sleske:是的,你是对的——这可以从相当早的 9.x 版本的 IDS 中获得,所有这些都已正式过时。【参考方案2】:

如果我理解您的问题,您对“TOP”有疑问。尝试使用 TOP-N 查询。

例如:

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

这将为您提供前 50 个结果(因为我在子查询中按 desc 排序)

【讨论】:

可能是一种解决方案,但在 Informix 中获取行号并不容易。见***.com/questions/119278/…。如果可能的话,我不想也不使用临时表和序列。 rownum 不是 Informix SQL。这只 (?) 对 Oracle 有效。

以上是关于带有 FIRST 选项的 Informix 子查询的主要内容,如果未能解决你的问题,请参考以下文章

gbase(Informix) pageHelper修改分页语句

gbase(Informix) pageHelper修改分页语句

Informix “发生了语法错误。”使用子查询时

informix 数据库的分页

Entity Framework 5 Code First 到现有 Informix 数据库

在 Informix DB 中更改表查询