powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / CASE WHEN с множеством полей
20 сообщений из 20, страница 1 из 1
CASE WHEN с множеством полей
    #39022838
Majestio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрейшего времени суток!

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

Приведу "синтетический" пример:
Код: plsql
1.
2.
3.
4.
5.
SELECT
  CASE WHEN "Idx" = 1 THEN '1111' ELSE '*' END,
  CASE WHEN "Idx" = 1 THEN '2222' ELSE '*' END,
  CASE WHEN "Idx" = 1 THEN '3333' ELSE '*' END
FROM generate_series(1,3) AS "Idx";


Результат:
Код: sql
1.
2.
3.
4.
5.
6.
7.
---------------------
case1 | case2 | case3
---------------------
 1111 | 2222  | 3333
 *    | *     | *
 *    | *     | *
---------------------



Но таких кэйзов 37 блоков, в каждом блоке 25 штук. Хотелось бы сократить в нечто подобное ниже, но это не работает. Вернее выполняется успешно, но результат не тот, что нужен:

Код: plsql
1.
2.
3.
SELECT
  CASE WHEN "Idx" = 1 THEN ('1111','2222','3333') ELSE ('*','*','*') END
FROM generate_series(1,3) AS "Idx";



Иными словами, можно ли одним кейзом генерировать несколько полей сразу?
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39022869
p2.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Majestio,

Нужны именно раздельные поля? Вместо 37х25 кейзов можно применить 37 джоинов на 25 полей.
Но такая эстетика субъективна, а вот ресурсов может съесть чуть больше.
Код: sql
1.
2.
3.
4.
select t01.*
from generate_series(1,3) AS "Idx"
left join (select '1111', '2222', '3333') t01(a, b, c)
    on "Idx"=1

Если нужна именно *, то coalesce на каждое поле или уже накручивать lateral c union по Idx.
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39022873
Majestio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нужны именно кейзы, ибо внутри них сплошные агрегатные функции от запроса.
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39022888
Majestio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Опубликую сырой вид запроса, чтобы было понятно о чем речь:


Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
  SELECT
    x."FamilyId",  
    -- 3 + блок (многодетные семьи, > 2 детей)
    CASE WHEN SUM(x."x03")>2 THEN 1 ELSE 0 END AS "Z01-AA",                -- семей
    CASE WHEN SUM(x."x03")>2 THEN SUM(x."x01") ELSE 0 END AS "Z01-BB",     -- граждан в семях
    CASE WHEN SUM(x."x03")>2 THEN SUM(x."rC0") ELSE 0 END AS "Z01-CC",     -- патронатов
    CASE WHEN SUM(x."x03")>2 THEN SUM(x."r11") ELSE 0 END AS "Z01-01",     -- консультация (взрослые) Психлологическая
    CASE WHEN SUM(x."x03")>2 THEN SUM(x."r12") ELSE 0 END AS "Z01-02",     -- консультация (дети    ) Психлологическая
    CASE WHEN SUM(x."x03")>2 THEN SUM(x."r21") ELSE 0 END AS "Z01-21",     -- консультация (взрослые) Педагогическая
    CASE WHEN SUM(x."x03")>2 THEN SUM(x."r22") ELSE 0 END AS "Z01-22",     -- консультация (дети    ) Педагогическая
    CASE WHEN SUM(x."x03")>2 THEN SUM(x."r21") ELSE 0 END AS "Z01-31",     -- консультация (взрослые) Юридическая
    CASE WHEN SUM(x."x03")>2 THEN SUM(x."r22") ELSE 0 END AS "Z01-32",     -- консультация (дети    ) Юридическая
    CASE WHEN SUM(x."x03")>2 THEN SUM(x."r21") ELSE 0 END AS "Z01-41",     -- консультация (взрослые) Индивидуально-коррекционная
    CASE WHEN SUM(x."x03")>2 THEN SUM(x."r22") ELSE 0 END AS "Z01-42",     -- консультация (дети    ) Индивидуально-коррекционная
    -- и еще 14 кейзов
    
    -- ... и еще 36 таких блоков
  FROM (  
    SELECT
      x."Id",
      x."FamilyId",
      x."Age",
      x."Sex",
      x."IsChild",
      x."IsParent",
      x."x01",x."x02",x."x03",x."x04",x."x05",
      x."x06",x."x07",x."x08",x."x09",x."x10",
      x."x11",x."x12",x."x13",x."x14",x."x15",
      x."x16",x."x17",x."x19",x."x20",x."x21",
      x."x23",x."x24",x."x25",x."x26",x."x27",
      x."x29",x."x30",x."x31",x."x32",x."x33",
      SUM(x."r11") AS "r11",
      SUM(x."r12") AS "r12",
      SUM(x."r21") AS "r21",
      SUM(x."r22") AS "r22",
      SUM(x."r31") AS "r31",
      SUM(x."r32") AS "r32",
      SUM(x."r41") AS "r41",
      SUM(x."r42") AS "r42",
      SUM(x."r51") AS "r51",
      SUM(x."r52") AS "r52",
      SUM(x."r61") AS "r61",
      SUM(x."r62") AS "r62",
      SUM(x."r71") AS "r71",
      SUM(x."r72") AS "r72",
      SUM(x."r81") AS "r81",
      SUM(x."r82") AS "r82",
      SUM(x."r91") AS "r91",
      SUM(x."r92") AS "r92",
      SUM(x."rA1") AS "rA1",
      SUM(x."rA2") AS "rA2",
      SUM(x."rB1") AS "rB1",
      SUM(x."rB2") AS "rB2",
      SUM(x."rC0") AS "rC0"
    FROM (
      SELECT
        f.*,
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1020 AND f."IsChild"=0 THEN 1 ELSE 0 END AS "r11",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1020 AND f."IsChild">0 THEN 1 ELSE 0 END AS "r12",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1022 AND f."IsChild"=0 THEN 1 ELSE 0 END AS "r21",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1022 AND f."IsChild">0 THEN 1 ELSE 0 END AS "r22",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1025 AND f."IsChild"=0 THEN 1 ELSE 0 END AS "r31",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1025 AND f."IsChild">0 THEN 1 ELSE 0 END AS "r32",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1014 AND f."IsChild"=0 THEN 1 ELSE 0 END AS "r41",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1014 AND f."IsChild">0 THEN 1 ELSE 0 END AS "r42",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1013 AND f."IsChild"=0 THEN 1 ELSE 0 END AS "r51",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1013 AND f."IsChild">0 THEN 1 ELSE 0 END AS "r52",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1019 AND f."IsChild"=0 THEN 1 ELSE 0 END AS "r61",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1019 AND f."IsChild">0 THEN 1 ELSE 0 END AS "r62",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1015 AND f."IsChild"=0 THEN 1 ELSE 0 END AS "r71",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1015 AND f."IsChild">0 THEN 1 ELSE 0 END AS "r72",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1018 AND f."IsChild"=0 THEN 1 ELSE 0 END AS "r81",
        CASE WHEN COALESCE(pr1."Rubrica",0) = 1018 AND f."IsChild">0 THEN 1 ELSE 0 END AS "r82",
        CASE WHEN COALESCE(pr2."Rubrica",0) = 1211 AND f."IsChild"=0 THEN 1 ELSE 0 END AS "r91",
        CASE WHEN COALESCE(pr2."Rubrica",0) = 1211 AND f."IsChild">0 THEN 1 ELSE 0 END AS "r92",
        CASE WHEN COALESCE(pr2."Rubrica",0) IN (1047,1049) AND f."IsChild"=0 THEN 1 ELSE 0 END AS "rA1",
        CASE WHEN COALESCE(pr2."Rubrica",0) IN (1047,1049) AND f."IsChild">0 THEN 1 ELSE 0 END AS "rA2",
        CASE WHEN COALESCE(pr2."Rubrica",0) = 1044 AND f."IsChild"=0 THEN 1 ELSE 0 END AS "rB1",
        CASE WHEN COALESCE(pr2."Rubrica",0) = 1044 AND f."IsChild">0 THEN 1 ELSE 0 END AS "rB2",
        CASE WHEN COALESCE(pr3."Rubrica",0) > 0 THEN 1 ELSE 0 END AS "rC0"
      FROM
        "FamilyOnPeriod"('2015-01-01','2015-12-31') AS f
      LEFT JOIN
        "Service2Clients" AS sc ON
          sc."Client" = f."Id"
      LEFT JOIN
        "Service" AS s ON
          s."Id" = sc."Service" AND
          s."Date" BETWEEN '2015-01-01' AND '2015-12-31'
      LEFT JOIN
        "Points2Rubrica" AS pr1 ON
          pr1."Point" = s."Id" AND
          pr1."System" & 8 = 8 AND
          pr1."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 123)
      LEFT JOIN
        "Points2Rubrica" AS pr2 ON
          pr2."Point" = s."Id" AND
          pr2."System" & 8 = 8 AND
          pr2."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 118)
      LEFT JOIN
         "Points2Rubrica" AS pr3 ON
           pr3."Point" = f."Id" AND
           pr3."System" & 2 = 2 AND
           pr3."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 142)
    ) AS x
    GROUP BY
      x."Id",
      x."FamilyId",
      x."Age",
      x."Sex",
      x."IsChild",
      x."IsParent",
      x."x01",x."x02",x."x03",x."x04",x."x05",
      x."x06",x."x07",x."x08",x."x09",x."x10",
      x."x11",x."x12",x."x13",x."x14",x."x15",
      x."x16",x."x17",x."x19",x."x20",x."x21",
      x."x23",x."x24",x."x25",x."x26",x."x27",
      x."x29",x."x30",x."x31",x."x32",x."x33"
  ) AS x
  GROUP BY
    x."FamilyId"



В запросе используется функция:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
CREATE OR REPLACE FUNCTION public."FamilyOnPeriod" (
  DateBegin date,
  DateEnd date
)
RETURNS TABLE (
  "Id" integer,
  "FamilyId" integer,
  "Age" integer,
  "Sex" integer,
  "IsChild" integer,
  "IsParent" integer,
  x01 integer, -- это человек семьи (для просчета количества людей в семье)
  x02 integer, -- это ребенок до 14 лет
  x03 integer, -- это ребенок до 18 лет
  x04 integer, -- это родитель, для подсчета родителей
  x05 integer, -- это молодая семья
  x06 integer, -- это вдова или вдовец
  x07 integer, -- это женщина-мать, родившая вне брака
  x08 integer, -- это несовершеннолетняя одинокая мать
  x09 integer, -- это одинокая мать, получающая пособие
  x10 integer, -- это разведенный родитель
  x11 integer, -- это семья усыновителей + родитель
  x12 integer, -- это гражданин пожилого возраста
  x13 integer, -- это одиноко-проживающий гражданин пожилого возраста
  x14 integer, -- это инвалид I-II группы
  x15 integer, -- это одиноко-проживающий инвалид I-II группы
  x16 integer, -- это выпускник-родитель
  x17 integer, -- это пенсионер
  x19 integer, -- несовершеннолетний родитель
  x20 integer, -- несовершеннолетний родитель из числа детей-сирот
  x21 integer, -- родитель-инвалид I-II группы
  x23 integer, -- ребенок в социально-опасном положении
  x24 integer, -- ребенок-инвалид с детства
  x25 integer, -- ребенок из числа детей сирот
  x26 integer, -- ребенок выпускник интернат
  x27 integer, -- ребенок c болезнями
  x29 integer, -- из семьи беженцев
  x30 integer, -- из семьи опекунов
  x31 integer, -- из семьи приемной
  x32 integer, -- из семьи отселенной
  x33 integer  -- из семьи, получающей пособие
) AS
$body$
BEGIN
  RETURN QUERY 
      SELECT
        x."Id"::INTEGER,
        x."FamilyId"::INTEGER,
        x."Age"::INTEGER,
        x."Gender"::INTEGER,
        x."IsChild"::INTEGER,
        x."IsParent"::INTEGER,
        -- это человек семьи (для просчета количества людей в семье)
        1::INTEGER AS "X01",
        -- это ребенок до 14 лет
        CASE WHEN x."IsChild">0 AND x."Age"<14 THEN 1::INTEGER ELSE 0::INTEGER END AS "X02",                                   
        -- это ребенок до 18 лет
        CASE WHEN x."IsChild">0 THEN 1::INTEGER ELSE 0::INTEGER END AS "X03",
        -- это родитель, для подсчета родителей
        CASE WHEN x."IsParent">0 THEN 1::INTEGER ELSE 0::INTEGER END AS "X04",
        -- это молодая семья                             
        CASE WHEN x."R10">0 THEN 1::INTEGER ELSE 0::INTEGER END AS "X05",
        -- это вдова или вдовец                             
        CASE WHEN x."R01" = 694 THEN 1::INTEGER ELSE 0::INTEGER END AS "X06",
        -- это женщина-мать, родившая вне брака
        CASE WHEN (x."R01" NOT IN (692,693,694)) AND (x."Gender">0) AND (x."IsParent">0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X07",
        -- это несовершеннолетняя одинокая мать
        CASE WHEN (x."R01" NOT IN (692,697)) AND (x."Gender">0) AND (x."IsParent">0) AND (x."Age"<18) THEN 1::INTEGER ELSE 0::INTEGER END AS "X08",
        -- это одинокая мать, получающая пособие
        CASE WHEN (x."R01" NOT IN (692,697)) AND (x."Gender">0) AND (x."IsParent">0) AND (x."R11">0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X09",
        -- это разведенный родитель
        CASE WHEN (x."R01" = 693) AND (x."IsParent">0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X10",
        -- это семья усыновителей + родитель
        CASE WHEN (x."R12" > 0) AND (x."IsParent">0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X11",
        -- это гражданин пожилого возраста
        CASE WHEN (x."Age" > 60) THEN 1::INTEGER ELSE 0::INTEGER END AS "X12",
        -- это одиноко-проживающий гражданин пожилого возраста
        CASE WHEN (x."Age" > 60) AND (x."R03" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X13",
        -- это инвалид I-II группы
        CASE WHEN (x."R02" IN (863,864)) THEN 1::INTEGER ELSE 0::INTEGER END AS "X14",
        -- это одиноко-проживающий инвалид I-II группы
        CASE WHEN (x."R02" IN (863,864)) AND (x."R03" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X15",
        -- это выпускник-родитель
        CASE WHEN (x."IsParent" > 0) AND (x."R04" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X16",
        -- это пенсионер
        CASE WHEN (x."R05" > 0) OR (x."R08" = 858) THEN 1::INTEGER ELSE 0::INTEGER END AS "X17",
        -- несовершеннолетний родитель
        CASE WHEN (x."IsParent" > 0) AND (x."Age" < 18) THEN 1::INTEGER ELSE 0::INTEGER END AS "X19",
        -- несовершеннолетний родитель из числа детей-сирот
        CASE WHEN (x."IsParent" > 0) AND (x."Age" < 18) AND (x."R09" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X20",
        -- родитель-инвалид I-II группы
        CASE WHEN (x."IsParent" > 0) AND (x."R02" IN (863,864)) THEN 1::INTEGER ELSE 0::INTEGER END AS "X21",
        -- ребенок в социально-опасном положении
        CASE WHEN (x."IsChild" > 0) AND (x."R06" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X23",
        -- ребенок-инвалид с детства
        CASE WHEN (x."IsChild" > 0) AND (x."R02" = 1235) THEN 1::INTEGER ELSE 0::INTEGER END AS "X24",
        -- ребенок из числа детей сирот
        CASE WHEN (x."IsChild" > 0) AND (x."R09" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X25",
        -- ребенок выпускник интернат
        CASE WHEN (x."IsChild" > 0) AND (x."R04" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X26",
        -- ребенок c болезнями
        CASE WHEN (x."IsChild" > 0) AND (x."R07" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X27",
        -- из семьи беженцев
        CASE WHEN (x."R14" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X29",
        -- из семьи опекунов
        CASE WHEN (x."R13" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X30",
        -- из семьи приемной
        CASE WHEN (x."R15" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X31",
        -- из семьи отселенной
        CASE WHEN (x."R16" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X32",
        -- из семьи, получающей пособие
        CASE WHEN (x."R11" > 0) THEN 1::INTEGER ELSE 0::INTEGER END AS "X33"
      FROM (
        SELECT
          x.*,
          COALESCE(pr01."Rubrica",0) AS "R01", -- Семейное положение
          COALESCE(pr02."Rubrica",0) AS "R02", -- Инвалидность
          COALESCE(pr03."Rubrica",0) AS "R03", -- Одинокое проживание
          COALESCE(pr04."Rubrica",0) AS "R04", -- Выпускник интернатных учреждений             
          COALESCE(pr05."Rubrica",0) AS "R05", -- Пенсионер
          COALESCE(pr06."Rubrica",0) AS "R06", -- Социально опасное положение              
          COALESCE(pr07."Rubrica",0) AS "R07", -- Наличие заболеваний
          COALESCE(pr08."Rubrica",0) AS "R08", -- Социальный статус
          COALESCE(pr09."Rubrica",0) AS "R09", -- Из числа детей-сирот
          COALESCE(pr10."Rubrica",0) AS "R10", -- Молодая семья                 
          COALESCE(pr11."Rubrica",0) AS "R11", -- Получение пособий 
          COALESCE(pr12."Rubrica",0) AS "R12", -- Семья усыновителей               
          COALESCE(pr13."Rubrica",0) AS "R13", -- Опекунская семья                   
          COALESCE(pr14."Rubrica",0) AS "R14", -- Семья беженцев
          COALESCE(pr15."Rubrica",0) AS "R15", -- Приемная семья
          COALESCE(pr16."Rubrica",0) AS "R16"  -- Отселенная семья
        FROM (
          SELECT
            x."Id",
            x."Age",
            CASE WHEN x."Gender" THEN 1::INTEGER ELSE 0::INTEGER END AS "Gender",
            x."FamilyId",
            CASE WHEN 
              SUM(CASE WHEN COALESCE(x."Childs1",0)>0 THEN 1 ELSE 0 END) = 0 AND 
              SUM(CASE WHEN COALESCE(fa2."Relation",0)>0 THEN 1 ELSE 0 END) = 0 AND
              x."Age" < 18 
              THEN 1::INTEGER ELSE 0::INTEGER END AS "IsChild",
            CASE WHEN 
              SUM(CASE WHEN COALESCE(x."Childs1",0)>0 THEN 1 ELSE 0 END) > 0 AND 
              SUM(CASE WHEN COALESCE(fa2."Relation",0)>0 THEN 1 ELSE 0 END) = 0
              THEN 1::INTEGER ELSE 0::INTEGER END AS "IsParent"
          FROM (
            SELECT
              c."Id",
              CASE WHEN c."YearOfBirth" < 150 THEN c."YearOfBirth" ELSE (EXTRACT(year FROM now()) - c."YearOfBirth") END AS "Age",
              c."Gender",
              c."FamilyId",
              CASE WHEN ((COALESCE(fa1."Relation",0)>0) AND (fa1."ClientOne" = c."Id")) THEN fa1."ClientTwo" 
                   WHEN ((COALESCE(fa1."Relation",0)>0) AND (fa1."ClientTwo" = c."Id")) THEN fa1."ClientOne" ELSE 0 END AS "Childs1"
            FROM
              "Clients" AS c
            LEFT JOIN
              "Family" AS fa1 ON
                (fa1."ClientOne" = c."Id" AND fa1."Relation" IN (15,16,19,20)) OR
                (fa1."ClientTwo" = c."Id" AND fa1."Relation" IN (10,21,22,30))
            WHERE
              c."FamilyId" IN (
                SELECT 
                  c."FamilyId"
                FROM
                  "Service" AS s,
                  "Service2Clients" AS sc,
                  "Clients" AS c
                WHERE 
                  c."Id" = sc."Client" AND 
                  sc."Service" = s."Id" AND 
                  s."Date" BETWEEN DateBegin AND DateEnd AND 
                  s."State" > 0 AND 
                  sc."Present"
              )
          ) AS x
          LEFT JOIN
            "Family" AS fa2 ON
              (fa2."ClientOne" = x."Childs1" AND fa2."Relation" IN (15,16,19,20)) OR
              (fa2."ClientTwo" = x."Childs1" AND fa2."Relation" IN (10,21,22,30))
          GROUP BY
            x."Id", x."Age", x."Gender", x."FamilyId"
        ) AS x
        LEFT JOIN "Points2Rubrica" AS pr01 ON 
          pr01."Point" = x."Id" AND pr01."System" & 2 = 2 AND 
          pr01."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 111)
        LEFT JOIN "Points2Rubrica" AS pr02 ON 
          pr02."Point" = x."Id" AND pr02."System" & 2 = 2 AND 
          pr02."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 100)
        LEFT JOIN "Points2Rubrica" AS pr03 ON 
          pr03."Point" = x."Id" AND pr03."System" & 2 = 2 AND 
          pr03."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 104)
        LEFT JOIN "Points2Rubrica" AS pr04 ON 
          pr04."Point" = x."Id" AND pr04."System" & 2 = 2 AND 
          pr04."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 156)
        LEFT JOIN "Points2Rubrica" AS pr05 ON 
          pr05."Point" = x."Id" AND pr05."System" & 2 = 2 AND 
          pr05."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 106)
        LEFT JOIN "Points2Rubrica" AS pr06 ON 
          pr06."Point" = x."Id" AND pr06."System" & 2 = 2 AND 
          pr06."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 130)
        LEFT JOIN "Points2Rubrica" AS pr07 ON 
          pr07."Point" = x."Id" AND pr07."System" & 2 = 2 AND 
          pr07."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 153)
        LEFT JOIN "Points2Rubrica" AS pr08 ON 
          pr08."Point" = x."FamilyId" AND pr08."System" & 2 = 2 AND 
          pr08."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 114)
        LEFT JOIN "Points2Rubrica" AS pr09 ON 
          pr09."Point" = x."FamilyId" AND pr09."System" & 2 = 2 AND 
          pr09."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 112)
        LEFT JOIN "Points2Rubrica" AS pr10 ON 
          pr10."Point" = x."FamilyId" AND pr10."System" & 4 = 4 AND 
          pr10."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 125)
        LEFT JOIN "Points2Rubrica" AS pr11 ON 
          pr11."Point" = x."FamilyId" AND pr11."System" & 4 = 4 AND 
          pr11."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 128)
        LEFT JOIN "Points2Rubrica" AS pr12 ON 
          pr12."Point" = x."FamilyId" AND pr12."System" & 4 = 4 AND 
          pr12."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 155)
        LEFT JOIN "Points2Rubrica" AS pr13 ON 
          pr13."Point" = x."FamilyId" AND pr13."System" & 4 = 4 AND 
          pr13."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 126)
        LEFT JOIN "Points2Rubrica" AS pr14 ON 
          pr14."Point" = x."FamilyId" AND pr14."System" & 4 = 4 AND 
          pr14."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 154)
        LEFT JOIN "Points2Rubrica" AS pr15 ON 
          pr15."Point" = x."FamilyId" AND pr15."System" & 4 = 4 AND 
          pr15."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 152)
        LEFT JOIN "Points2Rubrica" AS pr16 ON 
          pr16."Point" = x."FamilyId" AND pr16."System" & 4 = 4 AND 
          pr16."Rubrica" IN (SELECT r."Id" FROM "Rubricator" AS r WHERE r."GroupId" = 127)
      ) AS x;
END
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100 ROWS 10000;



Собственно, с этим и воюю :-\
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39022889
dmikelios
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SELECT '1111' AS case1, '2222' AS case2, '3333' AS case3
UNION ALL
SELECT '*', '*', '*'
FROM generate_series(1,3);
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39022894
p2.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MajestioОпубликуютебя же не смущает бесполезный COALESCE(pr1."Rubrica",0) в равенстве с ненулевой константой.
Если лень набирать буквы case ... else 0 end, замени на умножение на условие, приведенное к integer. А во внутреннем запросе и умножение не нужно.
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39022895
Majestio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
dmikelios , это не прокатит - только если для воспроизведения "синтетического" примера, и то с ошибкой (1 лишняя строка). Я выше опубликовал набросок запроса, посмотри, плс, как там все начинается и че с этим можно сделать.
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39022899
Majestio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
p2.MajestioОпубликуютебя же не смущает бесполезный COALESCE(pr1."Rubrica",0) в равенстве с ненулевой константой.

Оффтоп. Речь не об этом. И да, не смущает. В данном случая оптимизатор отрабатывает на отлично, а мне копипастить удобнее. Для примера ...

Этот запрос:
Код: plsql
1.
2.
3.
4.
5.
6.
SELECT
  CASE WHEN COALESCE(x."c",0)=1 THEN 1 ELSE 0 END
FROM (
 SELECT 1 AS c UNION
 SELECT NULL AS c 
) AS x


И этот запрос:
Код: plsql
1.
2.
3.
4.
5.
6.
SELECT
  CASE WHEN x."c"=1 THEN 1 ELSE 0 END
FROM (
 SELECT 1 AS c UNION
 SELECT NULL AS c 
) AS x


По эксплайну строго идентичны:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
Subquery Scan on x  (cost=0.05..0.09 rows=2 width=4)
  ->  Unique  (cost=0.05..0.06 rows=2 width=0)
        ->  Sort  (cost=0.05..0.06 rows=2 width=0)
              Sort Key: (1)
              ->  Append  (cost=0.00..0.04 rows=2 width=0)
                    ->  Result  (cost=0.00..0.01 rows=1 width=0)
                    ->  Result  (cost=0.00..0.01 rows=1 width=0)
Time: 0.019s


Поэтому давай по теме попробуем продолжить.
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39022904
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Majestio,

Ваша проблема разобрана например тут
http://www.postgresql.org/message-id/flat/CAMr3DCMJfbxFAK08rpOZSoGKNMCA+fM+YO6X=RkTeczrX_8sLQ@mail.gmail.com#CAMr3DCMJfbxFAK08rpOZSoGKNMCA+fM+YO6X=RkTeczrX_8sLQ@mail.gmail.com]http://www.postgresql.org/message-id/flat/CAMr3DCMJfbxFAK08rpOZSoGKNMCA fM YO6X=RkTeczrX_8sLQ@mail.gmail.com#CAMr3DCMJfbxFAK08rpOZSoGKNMCA fM YO6X=RkTeczrX_8sLQ@mail.gmail.com

Я бы посоветовал делать через регистрацию кастомного типа. Это самый прямой метод для вашей задачи.
Как то так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
create type foo as (f1 text, f2 text, f3 text);
CREATE TYPE
select (_f).*  from (select CASE WHEN "Idx" = 1 THEN ('1111','2222','3333')::foo ELSE ('*','*','*')::foo END as _f FROM generate_series(1,3) AS "Idx") as _t;
  f1  |  f2  |  f3
------+------+------
 1111 | 2222 | 3333
 *    | *    | *
 *    | *    | *
(3 rows)



--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39022913
Majestio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Maxim, спасибо!
Попробую поэкспериментировать, посмотрю на сколько станет удобнее и быстрее/медленнее.
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39022923
dmikelios
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Majestio,

Если использовать CTE и UNION, то можно избавиться от CASE-ов, но, наверное, будет работать медленнее,
чем в Вашем исходном варианте.

WITH x2 AS
(SELECT x."FamilyId", SUM(x."x03") AS "x03", SUM(x."x01") AS "x01", ..., SUM(x."r22") AS "r22"
FROM (...) AS x
GROUP BY x."FamilyId"
)
SELECT x2."FamilyId", 1 AS "Z01-AA", x2."x01" AS "Z01-BB", ..., x2."r22" AS "Z01-42"
FROM x2 WHERE x2."x03" > 2
UNION ALL
SELECT x2."FamilyId", 0 AS "Z01-AA", 0 AS "Z01-BB", ..., 0 AS "Z01-42"
FROM x2 WHERE x2."x03" <= 2;
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39022924
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MajestioПо эксплайну строго идентичныТо, что в плане синтетического запроса не отражена стоимость скалярных выражений, никак не дает понимания целей изысков. В начальной постановке озвучена эстетическая цель. По этому критерию лишние символы
Код: sql
1.
CASE WHEN COALESCE(x."c",0)=1 THEN 1 ELSE 0 END

противоречат моим представлениям. И с точностью до null заменимо на
Код: sql
1.
(x."c"=1)::integer

так как далее интерпретируется только true/1.
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39023007
Majestio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-2-так как далее интерпретируется только true/1.
Мне не нужны NULL'и в промежуточном результате.
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39023011
biwed.ru
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Majestio, Добрый день.
MajestioВ результате составления запроса на очередную форму отчетности - получается не совсем красивая конструкция. Хотелось бы ее как-то оптимизировать.

ИМХО. Делайте отчетность на OLAP кубах и будет вам счастье. Как вариант Postgresql + Pentaho (ROLAP).

С уважением,
biwed.ru
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39023014
Majestio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
biwed.ruИМХО. Делайте отчетность на OLAP кубах и будет вам счастье.
Спасибо за совет. Бегло посмотрел - интересно. Но пока, увы, проект горит - последний отчет доделываю и на сдачу. Нет времени для освоения и внедрения "на лету".
biwed.ruКак вариант Postgresql + Pentaho (ROLAP)
Посмотрел Pentaho. Возможно продукт хороший, но увы, платный. Я же в своей работе всегда пользуюсь исключительно бесплатными решениями: сервер как правило FreeBSD, реже линух, DB - pgsql, клиентские части - Qt5 некоммерческая лицензия. Но идею понял, попробую найти из OLAP что-то более другое, бесплатное. Еще раз спасибо.
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39023025
mad_nazgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MajestioПосмотрел Pentaho. Возможно продукт хороший, но увы, платный. Я же в своей работе всегда пользуюсь исключительно бесплатными решениями: сервер как правило FreeBSD, реже линух, DB - pgsql, клиентские части - Qt5 некоммерческая лицензия. Но идею понял, попробую найти из OLAP что-то более другое, бесплатное. Еще раз спасибо.

Вроде бы у Pentaho есть бесплатная версия.
А так, сам Pentaho сделан на свободном движке Mordrian.
Так что если есть желание попрограммировать, то можно взять Mordrian.
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39023060
biwed.ru
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Majestio, Добрый день.
MajestioПосмотрел Pentaho. Возможно продукт хороший, но увы, платный. Я же в своей работе всегда пользуюсь исключительно бесплатными решениями: сервер как правило FreeBSD, реже линух, DB - pgsql, клиентские части - Qt5 некоммерческая лицензия. Но идею понял, попробую найти из OLAP что-то более другое, бесплатное. Еще раз спасибо.

Это вы не погуглили даже. Есть Pentaho CE (Community Edition) http://community.pentaho.com/ Более подробно тут в этом топике: http://www.sql.ru/forum/1086007/kto-nibud-polzuet-pentaho

PS. Сам работаю на стеке Pentaho CE + PostgreSQL.

С уважением,
biwed.ru
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39023190
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. т.к. ф-я у вас security invoker -- переделайте её на language sql
2 я бы все же вынес агрегирование в подзапрос|cte, а case -ы исчислял уже над результатами -- т.к. у вас всё равно всё агрегируется до разбора кейсов. Вероятно оптимайзер с этим справляется и сам [отождествляя одинаковые агрегаты] -- но зачем его напрягать лишним разбором. [А если не справляется -- у вас кучи подсчетов дублей агрегатов.]

а вот что меньше всего бы меня беспокоило -- так это лаконичность выражения. нужна легко оптимизируемая, а не лаконичная декларация.
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39023974
Majestio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
qwwq1. т.к. ф-я у вас security invoker -- переделайте её на language sql
2 я бы все же вынес агрегирование в подзапрос|cte, а case -ы исчислял уже над результатами -- т.к. у вас всё равно всё агрегируется до разбора кейсов. Вероятно оптимайзер с этим справляется и сам [отождествляя одинаковые агрегаты] -- но зачем его напрягать лишним разбором. [А если не справляется -- у вас кучи подсчетов дублей агрегатов.]

а вот что меньше всего бы меня беспокоило -- так это лаконичность выражения. нужна легко оптимизируемая, а не лаконичная декларация.
Вы правы. Но время уж сильно торопит, надо сдаваться - оптимизировать некогда. Да и запрос, по скорости выполнения, пока устраивает - на 3000 записях в двух основных таблицах отрабатывает примерно 1-1.5 сек. Это приемлемо, ожидается 500-1000 записей в год. Сдамся, потом посмотрю в сторону оптимизации. А пока взял да и написал на Perl'е скрипт, который догенерил мне SQL запрос. Увы, сюда не могу вставить - форум говорит 100кб максимум на сообщение.
...
Рейтинг: 0 / 0
CASE WHEN с множеством полей
    #39023976
Majestio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
biwed.ruЭто вы не погуглили даже. Есть Pentaho CE (Community Edition) http://community.pentaho.com/ Более подробно тут в этом топике: http://www.sql.ru/forum/1086007/kto-nibud-polzuet-pentaho

Спасибо. Взял на заметочку.
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / CASE WHEN с множеством полей
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]