Как правильно использовать условную группу по агрегатам - PullRequest
0 голосов
/ 07 февраля 2019

Я хочу иметь возможность подсчитать общий тип яблок (только органических) с каждого континента с разбивкой по странам;включая общее количество, если они смешаны.

Например, продукт питания B1 - это органические золотые яблоки из США.Таким образом, должно быть количество «1» golden_bag и «1» для органических.Теперь, A1 также является органическим из Аргентины - однако, у него есть и бабушка и красные восхитительные яблоки - таким образом это подсчитывается как "1" mixed_bag и "1" для granny_bag и "1" для red_bag также.

Наконец, E1 и F1 - оба яблоки Фуджи из Лаоса, но одно органическое, другое нет;таким образом, общее количество равно 2 fuji_bag, и оно должно иметь общее число 1 для Organic_fd.

Table X:
food_item | food_area | food_loc   | food_exp
A1          lxgs        argentina   1/1/20
B1          iyan        usa         5/31/21
C1          lxgs        peru        4/1/20
D1          wa8e        norway      10/1/19
E1          894a        laos        5/1/19
F1          894a        laos        9/17/19


Table Y:
food_item | organic
A1          Y
B1          Y
C1          N
D1          N
E1          Y
F1          N

Table Z:
food_item | food_type
A1          189
A1          190
B1          191
C1          189
D1          192
E1          193
F1          193

SELECT continent, country,
      SUM(organic)  AS organic_fd, SUM(Granny) AS granny_bag,
      SUM(Red_delc) AS red_bag,    SUM(Golden) AS golden_bag,
      SUM(Gala)     AS gala_bag,   SUM(Fuji)   AS fuji_bag,
      SUM(CASE WHEN Granny + Red_delc + Golden + Gala + Fuji > 1 THEN 1  ELSE 0 END) AS mixed_bag     
FROM (SELECT (CASE SUBSTR (x.food_area, 4, 1)
              WHEN 's' THEN 'SA' WHEN 'n' THEN 'NA'
              WHEN 'e' THEN 'EU' WHEN 'a' THEN 'AS' ELSE NULL END) continent,
          x.food_loc country, COUNT(y.organic) AS Organic
          COUNT(CASE WHEN z.food_type = '189' THEN 1 END) AS Granny,
          COUNT(CASE WHEN z.food_type = '190' THEN 1 END) AS Red_delc,
          COUNT(CASE WHEN z.food_type = '191' THEN 1 END) AS Golden,
          COUNT(CASE WHEN z.food_type = '192' THEN 1 END) AS Gala,
          COUNT(CASE WHEN z.food_type = '193' THEN 1 END) AS Fuji      
    FROM x LEFT JOIN z ON x.food_item = z.food_item
           LEFT JOIN y on x.food_item = y.food_item and y.organic = 'Y'    
               WHERE  x.exp_date > sysdate
    GROUP BY SUBSTR (x.food_area, 4, 1), x.food_loc, y.organic) h
GROUP BY h.continent, h.country, h.organic

Я не получаю правильный вывод, так как, например, Лаос покажет ДВАЖДЫ для учета органического количестваи неорганический подсчет.Таким образом, он покажет 1 organic_fd и 0 organic_fd и 1 fuji_bag, а другая строка будет другой 1 fuji_bag.Я хотел бы ПОЛНЫЙ счет.(Кроме того, если я добавлю больше продуктов, мой смешанный_баг будет отображать в основном число «1» для каждой записи / строк).

Ниже приведен желаемый результат:

| continent | country   |organic_fd | granny_bag| red_bag| golden_bag| gala_bag|fuji_bag | mixed_bag
| SA        | argentina |    1      | 1         |   1    | 0         | 0       | 0       | 1
| SA        | peru      |    0      | 1         |   0    | 0         | 0       | 0       | 0
| NA        | usa       |    1      | 0         |   0    | 1         | 0       | 0       | 0
| EU        | norway    |    0      | 0         |   0    | 0         | 1       | 0       | 0
| AS        | laos      |    1      | 0         |   0    | 0         | 0       | 2       | 0

Итак, скажем, я хочу добавить еще один продукт, G1 из Норвегии, и в нем есть 3 типа органических яблок: fuji, red, granny ...тогда Норвегия теперь будет иметь счет 1 для следующих столбцов: mixed_bag, organic_fd, fuji_bag, red_bag, granny_bag (в дополнение к предыдущему счету 1 gala_bag).Если вы добавите H1, который в точности совпадает с G1, то теперь он будет иметь общее число 2 для следующих элементов: mixed_bag, organic_fd, fuji_bag, red_bag, granny_bag

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Запрос:

WITH
  t AS (
    SELECT
      CASE SUBSTR(X.food_area, LENGTH(X.food_area), 1)
        WHEN 's' THEN 'SA'
        WHEN 'n' THEN 'NA'
        WHEN 'e' THEN 'EU'
        WHEN 'a' THEN 'AS'
        ELSE NULL
      END AS continent,
      x.food_loc AS country,
      COUNT(DISTINCT CASE Y.organic WHEN 'Y' THEN X.food_item END) OVER (
        PARTITION BY x.food_loc
      ) AS organic_fd,
      CASE
        WHEN MIN(Z.food_type) OVER (
               PARTITION BY x.food_loc, X.food_item
             ) = Z.food_type AND
             MAX(Z.food_type) OVER (
               PARTITION BY x.food_loc, X.food_item
             ) > Z.food_type THEN 1 END AS mixed,
      Z.food_type
    FROM X
    JOIN Y ON X.food_item = Y.food_item
    JOIN Z ON Y.food_item = Z.food_item
  )
SELECT
  continent, country, organic_fd,
  COUNT(CASE WHEN food_type = '189' THEN 1 END) AS Granny,
  COUNT(CASE WHEN food_type = '190' THEN 1 END) AS Red_delc,
  COUNT(CASE WHEN food_type = '191' THEN 1 END) AS Golden,
  COUNT(CASE WHEN food_type = '192' THEN 1 END) AS Gala,
  COUNT(CASE WHEN food_type = '193' THEN 1 END) AS Fuji,
  COUNT(mixed) AS mixed_bag
FROM t
GROUP BY continent, country, organic_fd

Вы можете попробовать этот запрос здесь: https://rextester.com/TSSH87409.

0 голосов
/ 07 февраля 2019

У вас есть отношение один ко многим между x и z, и соединение может дать много строк для каждой строки в x, как в случае с A1.Поэтому сначала нужно пронумеровать строки в x, это то, что делает мой подзапрос t1, за исключением значений отображения.Затем сгруппируйте их, взяв max() для каждого подсчитанного столбца (бабушки, органические и т. Д.), Как в подзапросе t2.Окончательно суммируйте значения.

Демо-версия dbfiddle

with
  t1 as (
    select rn, food_item, food_area, food_loc country, food_exp, food_type,
           decode(substr(food_area, 4, 1), 's', 'SA', 'n', 'NA', 'e', 'EU', 'a', 'AS') continent,
           case organic when 'Y' then 1 else 0 end org,
           case when food_type = '189' then 1 else 0 end gra,
           case when food_type = '190' then 1 else 0 end red,
           case when food_type = '191' then 1 else 0 end gol,
           case when food_type = '192' then 1 else 0 end gal,
           case when food_type = '193' then 1 else 0 end fuj 
      from (select rownum rn, x.* from x) x join y using (food_item) join z using (food_item)
      where food_exp > sysdate),
  t2 as (
    select rn, country, continent, max(org) org, max(gra) gra, 
           max(red) red, max(gol) gol, max(gal) gal, max(fuj) fuj,
           case when max(gra) + max(red) + max(gol) + max(gal) + max(fuj) > 1 
                then 1 else 0 
            end mix
       from t1 group by rn, country, continent)
select continent, country, sum(org) organic_fd, sum(gra) granny, sum(red) red_delc, 
       sum(gol) golden_bag, sum(gal) gala_bag, sum(fuj) fuji_bag, sum(mix) mixed_bag 
  from t2 
  group by continent, country

Приведенный выше запрос дал ожидаемый результат, проверьте его и настройтеесли нужно.Я заметил, что вы используете левые соединения.Если существует вероятность того, что для некоторых строк в X нет данных в Y или Z, возможно, вам придется добавить nvl() s в вычислениях.Возможно, вам также следует поместить сопоставленные, жестко закодированные значения в таблицы.Жесткое их кодирование не является хорошей практикой.Надеюсь, это поможет:)

...