2013-04-11 2 views
2

У меня есть таблица с именем «where_clauses», которая содержит кучу условий, которые я хотел бы использовать для построения динамических запросов. Я хотел бы знать все возможные запросы, которые я мог бы выполнить, используя эти данные. Вот мои «where_clauses» данные ...Создание несколько сложного декартова результата

INSERT INTO where_clauses (id,col_name,clause) VALUES (1,'x','x < 1'); 
INSERT INTO where_clauses (id,col_name,clause) VALUES (2,'x','x < 2'); 
INSERT INTO where_clauses (id,col_name,clause) VALUES (3,'x','x < 3'); 
INSERT INTO where_clauses (id,col_name,clause) VALUES (4,'y','y < 1'); 
INSERT INTO where_clauses (id,col_name,clause) VALUES (5,'y','y < 2'); 
INSERT INTO where_clauses (id,col_name,clause) VALUES (6,'y','y < 3'); 
INSERT INTO where_clauses (id,col_name,clause) VALUES (7,'z','z < 1'); 

В идеале я хотел бы, чтобы «все возможные запросы» в виде массива идентификаторов. Например, результат «всех возможных запросов» будет ...

{1} 
{1,4} 
{1,4,7} 
{1,5} 
{1,5,7} 
{1,6} 
{1,6,7} 
{2} 
{2,4} 
{2,4,7} 
{2,5} 
{2,5,7} 
{2,6} 
{2,6,7} 
{3} 
{3,4} 
{3,4,7} 
{3,5} 
{3,5,7} 
{3,6} 
{3,6,7} 
{4} 
{4,7} 
{5} 
{5,7} 
{6} 
{6,7} 
{7} 

Обратите внимание, что im бросает соединение на равные столбцы. Что такое запрос, который даст все возможные where_clauses?

ответ

0

Попробуйте этот код, он выбирает три колонки, те, которые не используются для пункта оставлены NULL, можно сцепить или манипулировать, что результат далее:

--all possibilities with only one clause 
SELECT 
    id AS ID1, NULL ID2, NULL AS ID3 
    FROM where_clauses 
--all possibilities with two clauses (xy,xz,yz) 
UNION 
SELECT 
    WC1.id AS ID1, WC2.id AS ID2, NULL AS ID3 
    FROM where_clauses WC1 
    CROSS JOIN where_clauses WC2 
    WHERE 
    WC1.col_name != WC2.col_name 
    AND WC1.id > WC2.id 
--all possibilities with an x and a y and a z clause 
UNION 
SELECT 
    WC1.id AS ID1, WC2.id AS ID2, WC3.id AS ID3 
    FROM where_clauses WC1 
    CROSS JOIN where_clauses WC2 
    CROSS JOIN where_clauses WC3 
    WHERE 
    WC1.col_name != WC2.col_name 
    AND WC1.id > WC2.id 

    AND WC1.col_name != WC3.col_name 
    AND WC1.id > WC3.id 

    AND WC2.col_name != WC3.col_name 
    AND WC2.id > WC3.id 

Here является скрипку.

EDIT: модифицированная скрипка слегка

+0

Как бы это выглядело с столбцами с именем a-z вместо x-z? –

+0

довольно долго, я думаю;) – DrCopyPaste

0
SELECT string_to_array(TRIM(x || ',' || y || ',' || z, ','), ',') 
FROM (
WITH sq AS (
    SELECT a.id x, b.id y, c.id z 
    FROM where_clauses a, where_clauses b, where_clauses c 
    WHERE a.col_name != b.col_name AND 
      a.col_name != c.col_name AND 
      b.col_name != c.col_name AND 
      a.id < b.id AND 
      b.id < c.id 
) 
SELECT x, y, z FROM sq 
UNION ALL 
SELECT distinct x, y, null::int FROM sq 
UNION ALL 
SELECT distinct y, z, null::int FROM sq 
UNION ALL 
SELECT distinct x, null::int, null::int FROM sq 
UNION ALL 
SELECT distinct y, null::int, null::int FROM sq 
UNION ALL 
SELECT distinct z, null::int, null::int FROM sq 
) ORDER BY 1; 

ли выше запроса помогает вам?

+0

Что бы это выглядело со столбцами с именем a-z вместо x-z? –

1

Это проблема, которую необходимо решить. newWITH RECURSIVE. Следующее обобщает на любое количество имен столбцов (не только x, y, z).

WITH RECURSIVE subq(a, x) AS 
    (VALUES (ARRAY[]::int[], NULL) /* initial */ 
    UNION ALL 
    SELECT subq.a || id, col_name FROM subq JOIN where_clauses 
    ON x IS NULL OR x < col_name) 
SELECT a FROM subq 
WHERE x IS NOT NULL; /* discard the initial empty array */ 
+0

Отлично. Это похоже на то, что мне нужно. Чтобы сделать это еще на один шаг, допустим, я добавляю в предложения INSERT INTO where_clauses (id, col_name, clause) VALUES (8, 'x', 'x> 1') ;. Как я мог бы реорганизовать этот запрос так, чтобы я мог получить ... {3,5,7,8}? –

+0

Потому что это больше, не зависит от 1, 2 и 3, верно? Если все ваши ограничения будут иметь неравенство, я думаю, что я избавлюсь от 'clause' и будет иметь столбцы' col_name', 'op' и' value' (просто число). Когда вам нужно, в последующих запросах вы можете восстановить предложение, объединив эти поля вместе. Теперь вместо сортировки только на 'col_name' используйте конкатенацию' col_name || op' как 'x' в подзапросе. Это понятно? –

+0

Прохладный, я сделал это до сих пор. У меня есть предыдущий рекурсивный запрос, который теперь работает в полях col_name, op и value, объединяя поля col_name || op. Теперь мне просто нужно выяснить, как обеспечить им не включая сверхплотные диапазоны. Т.е.: WHERE x> 2 AND x> 1. Должно ли это взять много заявлений дела? –

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