2013-05-10 2 views
2

у меня есть две таблицы, чья упрощенная структура выглядит следующим образом:SQL: Включение строки в столбцы для переменного Числа строк

RESPONSES 
id 
created 

ACCESSORY VALUES 
id 
response_id 
sensor_id 
value 

Я хочу, чтобы создать представление, которое выравнивает все значения аксессуаров для данного ответа в одну строки в течение периода времени (фильтрация по response.created). Я думаю, что мне нужна сводная таблица или Crosstab, но я не знаком с обоими, а примеры, которые я нашел, в основном имеют дело с известным количеством столбцов. Чтобы усложнить ситуацию, данный датчик мог появиться только в течение периода времени, если пользователь начал или остановил его отслеживание в течение рассматриваемого времени. В идеале я бы держал NULL в этой колонке для датчика в любых строках, когда его нет. Это возможно? Если да, то я на правильном пути или смотрю не туда?

SQL, чтобы получить данные в виде отдельных строк выглядит

SELECT r.id, a.sensor_id, a.value from results_response r 
INNER JOIN results_accessoryvalue a ON r.id = a.response_id 
WHERE r.installation_id = 40 
AND r.created BETWEEN '2013-04-01' AND '2013-05-01' 
ORDER BY r.created 

, но я не имею никакой удачи, пытаясь использовать его в кросс-таблице, потому что я не знаю, как определить динамические столбцы.

ответ

0

Это альтернативный подход с использованием PostgreSQL массивов

create table responses (
    id serial not null unique, 
    x integer, 
    created timestamp default now() 
); 

create table accessory (
    id serial not null, 
    responses_id integer references responses (id), 
    sensor_id integer, 
    value text, 
    created timestamp default now() 
); 

insert into responses (x) values (1), (2),(3),(4); 

insert into accessory (responses_id , sensor_id, value) values 
(1, 1, 'A'), (1, 2, 'Ab'), (1, 3, 'Ac'), (1, 4, 'Ad'), 
(2, 4, 'Ab'), (1, 2, 'bAb'), (3, 3, 'bAc'), (4, 4, 'bAd'); 

select *, array(
    select value 
    from accessory 
    where accessory.responses_id = responses.id 
    order by accessory.created 
    ) as accessory_values 
from responses; 

Результатом запроса включает столбец массива со всеми значениями аксессуаров, которые соответствуют response.id

+0

Это похоже на действительно хорошую альтернативу. Я забыл, что вы можете это сделать в Postgres. Полагаю, что я могу делать агрегацию внутри подзапроса. – Tom

+0

По какой-то причине соединение не работает в подвыборке. Если я жестко закодирую значение идентификатора таблицы ответов, я получаю данные, но когда я присоединяюсь, я получаю пустой массив.Это то, что выглядит SQL: 'SELECT created, array (выберите sensor_id from results_accessoryvalue, где response_id = results_flattenedresponse.id) FROM results_flattenedresponse' – Tom

+0

Я думаю, это потому, что select sensor_id из results_accessoryvalue, где response_id = results_flattenedresponse.id, этот код ссылается на две таблицы но только 1 находится в инструкции from –

3

вы должны использовать перекрестную таблицу с некоторым ДОБАВЛЕНИЕМ. У меня тоже была эта проблема, и я решил это для своего предложения.

первой установки CrossTab добавочному

трюк я использовал, чтобы создать 2 дополнительных функций. один для получения информации типа, необходимой в качестве набора результатов для функции кросс-таблицы. посмотрите на это:

CREATE OR REPLACE FUNCTION "TEMPORARY.TYPE.FROM.COLUMN"(text, text) 
    RETURNS text AS 
$BODY$ 
DECLARE 
    typestring TEXT; 
    returnrec RECORD; 
BEGIN 
    typestring := ''; 
    FOR returnrec IN EXECUTE $1 LOOP 
     typestring := typestring||', "'||returnrec."Column"||'" '||$2; 
    END LOOP; 

    RETURN typestring; 
END; 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 

Теперь мы можем написать нашу вторую функцию:

CREATE OR REPLACE FUNCTION "DYNAMIC.CROSSTAB"(text, text, text) 
    RETURNS text AS 
$BODY$ 
DECLARE 
    typestring TEXT; 
    executestring TEXT; 
BEGIN 
    DROP TABLE IF EXISTS "TBL.Crosstab"; 
    SELECT "REPORTING"."TEMPORARY.TYPE.FROM.COLUMN"($2,$3) INTO typestring; 
    executestring := 'CREATE TEMPORARY TABLE "TBL.Crosstab" AS (SELECT * FROM crosstab('''||$1||''','''||$2||''') AS (row_name DATE'||typestring||'));'; 
    EXECUTE executestring; 
    RETURN '"TBL.Crosstab"'; 
END; 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 

Чтобы создать перекрестную таблицу просто позвонить:

SELECT * FROM "DYNAMIC.CROSSTAB"(text, text, text); 

Возвращает имя из временной таблицы для вашего сессия заполнена вашим результатом. Мне это нужно.

Параметр Объяснение:

Первый = запрос, чтобы получить данные (должны иметь 3 колонки: ROW_NAME, кошки и значение)

Второй = запрос, чтобы получить ваши столбцы Wich возвращает все ваши категории (кошки)

третьего = The columntype для нашего временного типа

он не идеален, но FIT в наших потребностях. у нас есть утверждения, выборки которых состоят из более чем 450 coloumns и некоторых строк. надеюсь, что это помогает

Смежные вопросы