【问题标题】:Informix one to many format issueInformix 一对多格式问题
【发布时间】:2017-03-10 16:54:24
【问题描述】:

尝试将我的 Informix 查询结果格式从一对多关系修复。我当前的查询正在使用 JOIN 但每次与 JOIN ON 条件匹配时都会创建一个新行。我应该添加以下只是一个示例,实际数据是数千个条目,其中大约有 100 个唯一的“类别”条目,所以我不能硬编码 WHERE 语句,它需要读取每个条目并添加是否匹配。我尝试了一个 GROUP_CONCAT 但是只是返回了一个错误,猜测它不是一个 informix 函数,我也尝试阅读这个线程但还没有开始工作。 Show a one to many relationship as 2 columns - 1 unique row (ID & comma separated list)

任何帮助将不胜感激。

  • IBM/Informix-Connect 版本 3.70.UC4
  • IBM/Informix LIGBLS 库版本 5.00.UC5
  • IBM Informix 动态服务器版本 11.70.FC8W1

表格

电影

name    rating  movie_id
rio g   1   
horton  g   2
blade   r   3
lotr_1  pg13    4
lotr_2  pg13    5
paul_blart  pg  6

类别

cat_name    id
kids    1
comedy  2
action  3
fantasy 4

类别成员

movie_name  cat_name    catmem_id
lotr_1 action 1
lotr_1 fantasy 2
rio kids 3
rio comedy  4

当我使用时

#!/bin/bash

echo "SET isolation dirty read;
UNLOAD to /export/home/movie/movieDetail.unl DELIMITER ','
    SELECT a.name, a.rating, b.cat_name
      FROM movie a
      LEFT JOIN category b ON b.movie_name = a.name
;" | dbaccess thedb;

我得到的是

rio,g,kids
rio,g,comedy
lotr_1,pg13,action
lotr_1,pg13,fantasy

我想要的是

rio,g,kids,comedy
lotr_1,pg13,action,fantasy

【问题讨论】:

    标签: informix


    【解决方案1】:

    安装GROUP_CONCAT用户自定义聚合

    您必须将SO 715350(在您的问题中引用)中的GROUP_CONCAT 用户定义聚合安装到您的数据库中。 GROUP_CONCAT 聚合不是由 Informix 定义的,但如果您使用该问题中的 SQL,则可以添加该聚合。它与普通内置函数之间的一个区别是,您需要在需要使用它的服务器中的每个数据库中安装聚合。可能有一种方法可以进行“全局安装”(针对给定服务器中的所有数据库),但我忘记了(或者更准确地说,从未学过)如何进行。

    编写您的查询

    示例数据库列在底部:

    1. 问题中的查询没有运行:

      SELECT a.name, a.rating, b.cat_name
        FROM movie a
        LEFT JOIN category b ON b.movie_name = a.name;
      SQL -217: Column (movie_name) not found in any table in the query (or SLV is undefined).
      
    2. 这可以通过将category 更改为category_member 来解决。这会产生:

      SELECT a.name, a.rating, b.cat_name
        FROM movie a
        LEFT JOIN category_member b ON b.movie_name = a.name;
      rio           g       kids
      rio           g       comedy
      horton        g
      blade         r
      lotr_1        pg13    action
      lotr_1        pg13    fantasy
      lotr_2        pg13
      paul_blart    pg
      
    3. LEFT JOIN 似乎是不需要的。并且使用GROUP_CONCAT 会产生大约所需的答案:

      SELECT a.name, a.rating, GROUP_CONCAT(b.cat_name)
        FROM movie a
        JOIN category_member b ON b.movie_name = a.name
       GROUP BY a.name, a.rating;
      rio          g       kids,comedy
      lotr_1       pg13    action,fantasy
      
    4. 如果您将分隔符指定为,,则来自GROUP_CONCAT 运算符的数据中的逗号将被转义以避免歧义:

      SELECT a.NAME, a.rating, GROUP_CONCAT(b.cat_name)
        FROM movie a
        JOIN category_member b ON b.movie_name = a.NAME
       GROUP BY a.NAME, a.rating;
      rio,g,kids\,comedy
      lotr_1,pg13,action\,fantasy
      

      在标准 Informix 实用程序中,没有办法避免这种情况;他们不会以不明确的格式留下选定/卸载的数据。

    5. 我不相信数据库模式组织得很好。电影表没问题;类别表是好的;但是 Category_Member 表如果使用架构会更正统:

      DROP TABLE IF EXISTS category_member;
      CREATE TABLE category_member
      (
          movie_id INTEGER NOT NULL REFERENCES Movie(Movie_id),
          category_id INTEGER NOT NULL REFERENCES Category(Id),
          PRIMARY KEY(movie_id, category_id)
      );
      INSERT INTO category_member VALUES(4, 3);
      INSERT INTO category_member VALUES(4, 4);
      INSERT INTO category_member VALUES(1, 1);
      INSERT INTO category_member VALUES(1, 2);
      
      -- Use GROUP_CONCAT
      SELECT a.NAME, a.rating, GROUP_CONCAT(c.cat_name)
        FROM movie a
        JOIN category_member b ON b.movie_id = a.movie_id
        JOIN category c ON b.category_id = c.id
       GROUP BY a.NAME, a.rating;
      

      此查询的输出与上一个相同,但连接更正统。

    示例数据库

    DROP TABLE IF EXISTS movie;
    CREATE TABLE movie
    (
        name VARCHAR(20) NOT NULL UNIQUE,
        rating CHAR(4) NOT NULL,
        movie_id SERIAL NOT NULL PRIMARY KEY
    );
    INSERT INTO movie VALUES("rio", "g", 1);
    INSERT INTO movie VALUES("horton", "g", 2);
    INSERT INTO movie VALUES("blade", "r", 3);
    INSERT INTO movie VALUES("lotr_1", "pg13", 4);
    INSERT INTO movie VALUES("lotr_2", "pg13", 5);
    INSERT INTO movie VALUES("paul_blart", "pg", 6);
    
    DROP TABLE IF EXISTS category;
    CREATE TABLE category
    (
        cat_name VARCHAR(10) NOT NULL UNIQUE,
        id SERIAL NOT NULL PRIMARY KEY
    );
    INSERT INTO category VALUES("kids", 1);
    INSERT INTO category VALUES("comedy", 2);
    INSERT INTO category VALUES("action", 3);
    INSERT INTO category VALUES("fantasy", 4);
    
    DROP TABLE IF EXISTS category_member;
    CREATE TABLE category_member
    (
        movie_name VARCHAR(20) NOT NULL,
        cat_name VARCHAR(10) NOT NULL,
        catmem_id SERIAL NOT NULL PRIMARY KEY
    );
    INSERT INTO category_member VALUES("lotr_1", "action", 1);
    INSERT INTO category_member VALUES("lotr_1", "fantasy", 2);
    INSERT INTO category_member VALUES("rio", "kids", 3);
    INSERT INTO category_member VALUES("rio", "comedy", 4);
    

    【讨论】:

    • 是的,包含的表格是一个匆忙的示例,因此可能与 select 语句一起出现错误,所以感谢您的详细解释。我担心你会证实我的想法。我们有 100 多个分布式系统,拥有独特的管理员,因此必须做很多令人信服的工作才能执行。
    • 当您安装使用它的更新软件时,只需在下一次升级中安装 GROUP_CONCAT。是的,它实际上从来没有那么简单,但是您如何处理需要添加以使系统正常工作的其他 SPL?需要小心处理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多