尝试从一对多关系修复我的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)
任何帮助将不胜感激。
表
电影
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
category_member
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
答案 0 :(得分:2)
GROUP_CONCAT
用户定义的聚合您必须将GROUP_CONCAT
用户定义的聚合从SO 715350(在您的问题中引用)安装到您的数据库中。 GROUP_CONCAT
聚合不是由Informix定义的,但如果您使用该问题中的SQL,则可以添加该聚合。它与普通内置函数之间的一个区别是,您需要在需要使用它的服务器中的每个数据库中安装聚合。可能有办法进行全球安装' (对于给定服务器中的所有数据库),但我已经忘记了(或者,更确切地说,从未学过)如何做到这一点。
底部列出了示例数据库:
问题中的查询未运行:
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).
可以通过将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
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
如果您将分隔符指定为,
,则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实用程序中,没有办法避免这种情况;他们不会以模糊的格式留下选定/卸载的数据。
我不相信数据库架构组织得很好。电影表是好的; Category表是可以的;但如果使用模式,则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);