Как смоделировать group_concat в простой SQL - PullRequest
4 голосов
/ 27 февраля 2012

Я использую драйвер hxtt sql для файлов csv.Он поддерживает только простой sql.Есть ли способ симулировать групповой конкат, используя простые операторы SQL?

1 Ответ

3 голосов
/ 02 марта 2012

Насколько просто?Если вы можете использовать триггеры, то вы можете сделать это довольно просто.Я использовал этот прием раньше в SQLite3, когда мне нужно было group_concat (), который позволяет мне указывать порядок, в котором должны быть объединены значения (SQLite3 не предоставляет способ сделать это).

Допустим, у нас есть таблица, подобная этой:

CREATE TABLE t(v TEXT NOT NULL, num INTEGER NOT NULL UNIQUE);

, и вы хотите объединить значения v, упорядоченные по num, с некоторым символом-разделителем, например запятой.

CREATE TEMP TABLE c(v TEXT);
CREATE TEMP TABLE j(v TEXT);

CREATE TEMP TRIGGER j_ins BEFORE INSERT ON j
FOR EACH ROW
BEGIN
    UPDATE c SET v = v || ',' || NEW.v;
    INSERT INTO c (v) SELECT NEW.v WHERE NOT EXISTS (SELECT * FROM c);
    SELECT RAISE(IGNORE);
END;

Теперь мы можем:

INSERT INTO j (c) SELECT v FROM t ORDER BY num;
SELECT v FROM c; -- this should output the concatenation of the values of v in t
DELETE FROM c;

Наконец, это сеанс sqlite3, показывающий, что это работает:

SQLite version 3.7.4
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> CREATE TABLE t(v TEXT NOT NULL, num INTEGER NOT NULL UNIQUE);
sqlite> CREATE TEMP TABLE c(v TEXT);
sqlite> CREATE TEMP TABLE j(v TEXT);
sqlite> CREATE TEMP TRIGGER j_ins BEFORE INSERT ON j
   ...> FOR EACH ROW
   ...> BEGIN
   ...>     UPDATE c SET v = v || ',' || NEW.v;
   ...>     INSERT INTO c (v) SELECT NEW.v WHERE NOT EXISTS (SELECT * FROM c);
   ...>     SELECT RAISE(IGNORE);
   ...> END;
sqlite> insert into t (v, num) values (1, 0);
sqlite> insert into t (v, num) values (31, 1);
sqlite> insert into t (v, num) values (52, 2);
sqlite> insert into t (v, num) values (0, 3);
sqlite> SELECT v FROM c;
sqlite> INSERT INTO j (v) SELECT v FROM t ORDER BY num;
sqlite> SELECT v FROM c;
1,31,52,0
sqlite> SELECT v FROM j;
sqlite> DELETE FROM c;
sqlite> 

Теперь это не чистый SQL, поскольку он зависит от триггеров.Между рекурсивными триггерами и всеми способами выполнения условий в SQL у вас есть полная система Тьюринга.Но если у вас нет триггеров или процедурных расширений, нет таблиц генератора ... тогда не так уж много.

Я ничего не знаю о hxtt, так что, возможно, это вам не поможет.Но SQLite3 может справиться с CSV, поэтому, возможно, SQLite3 может помочь вам ...

...