Подсчет количества дел внутри дела - PullRequest
0 голосов
/ 11 сентября 2018

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

Я попытался создать вложенное выражение CASE, первое, которое просматривает транзакции на определенном уровне.год, второй просматривал сумму транзакции человека в определенном магазине, но Oracle не любил вложенные выражения CASE (если я не делал это неправильно).

Из этого примера SQL :

CREATE TABLE table_name ( PersonId, StoreId, AmountSpent, Year) as
  select 1, 1, 60, 2017 from dual union
  select 1, 1, 50, 2017  from dual union
  select 1, 2, 70, 2018 from dual union
  select 2, 1, 10, 2017 from dual union
  select 2, 1, 10, 2017  from dual union
  select 2, 1, 200, 2018  from dual union
  select 2, 2, 60, 2018 from dual union
  select 2, 2, 60, 2018  from dual union
  select 3, 1, 25, 2017 from dual union
  select 3, 2, 200, 2017 from dual union
  select 3, 2, 200, 2018  from dual;

Select
  StoreId,
  SUM(CASE WHEN Year = '2017'
        THEN AmountSpent
        ELSE 0
      End) Year17,
   SUM(CASE WHEN Year = '2018'
        THEN AmountSpent
        ELSE 0
      End) Year18
FROM table_name
GROUP BY StoreId;

   STOREID     YEAR17     YEAR18
---------- ---------- ----------
         1        145        200
         2        200        330

Может ли кто-нибудь сделать такой вывод?Я думаю, что некоторые цифры могут быть неверными, но кажется, что большинство людей понимают суть того, куда я иду.

+----+---------+------------+---------------------+-------------------+---------------------+---------------------+------------+-------------------+---------------------+
|    | STOREID | Y17_INCOME | Y17_SPENT_BELOW_100 | Y17_SPENT_100_150 | Y17_SPENT_ABOVE_150 | Y18_INCOME | Y18_SPENT_BELOW_100 | Y18_SPENT_100_150 | Y18_SPENT_ABOVE_150 |
+----+---------+------------+---------------------+-------------------+---------------------+------------+---------------------+-------------------+---------------------+
| 1  | 1       | 145        | 2                   | 1                 | 0                   | 200        | 2                   | 0                 | 1                   |
+----+---------+------------+---------------------+-------------------+---------------------+---------------------+------------+-------------------+---------------------+
| 2  | 2       | 200        | 0                   | 0                 | 1                   | 330        | 0                   | 0                 | 1                   |
+----+---------+------------+---------------------+-------------------+---------------------+------------+---------------------+-------------------+---------------------+

Не уверен, если это возможно, но было бы здорово, если так!

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Вы можете сделать итоги магазина / человека во встроенном представлении, которое само по себе производит:

SELECT
  StoreId,
  PersonId,
  Year,
  SUM(AmountSpent) AS TotalSpent
FROM table_name
GROUP BY
  StoreId,
  PersonId,
  Year
ORDER BY
  StoreId,
  Year,
  PersonId;

   STOREID   PERSONID       YEAR TOTALSPENT
---------- ---------- ---------- ----------
         1          1       2017        110
         1          2       2017         10
         1          3       2017         25
         1          2       2018        200
         2          3       2017        200
         2          1       2018         70
         2          2       2018         60
         2          3       2018        200

, а затем использовать несколько отдельных выражений и агрегатов во внешнем запросе:

SELECT
  StoreId,
  SUM(CASE WHEN Year = '2017'
        THEN TotalSpent
        ELSE 0
      END) Year17,
  COUNT(CASE WHEN Year = '2017'
        AND TotalSpent < 100
        THEN TotalSpent
      END) AS Year17lt100,
  COUNT(CASE WHEN Year = '2017'
        AND TotalSpent >= 100
        AND TotalSpent < 150
        THEN TotalSpent
      END) AS Year17gte100lt150,
  COUNT(CASE WHEN Year = '2017'
        AND TotalSpent >= 150
        THEN TotalSpent
      END) AS Year17gte150,
   SUM(CASE WHEN Year = '2018'
        THEN TotalSpent
        ELSE 0
      END) Year18,
  COUNT(CASE WHEN Year = '2018'
        AND TotalSpent < 100
        THEN TotalSpent
      END) AS Year18lt100,
  COUNT(CASE WHEN Year = '2018'
        AND TotalSpent >= 100
        AND TotalSpent < 150
        THEN TotalSpent
      END) AS Year18gte100lt150,
  COUNT(CASE WHEN Year = '2017'
        AND TotalSpent >= 150
        THEN TotalSpent
      END) AS Year18gte150
FROM (
  SELECT
    StoreId,
    PersonId,
    Year,
    SUM(AmountSpent) AS TotalSpent
  FROM table_name
  GROUP BY
    StoreId,
    PersonId,
    Year
)
GROUP BY StoreId
ORDER BY StoreId;

, который получает:

   STOREID     YEAR17 YEAR17LT100 YEAR17GTE100LT150 YEAR17GTE150     YEAR18 YEAR18LT100 YEAR18GTE100LT150 YEAR18GTE150
---------- ---------- ----------- ----------------- ------------ ---------- ----------- ----------------- ------------
         1        145           2                 1            0        200           0                 0            0
         2        200           0                 0            1        330           2                 0            1

Это не соответствует выводу на вашем изображении, но я думаю, что это неправильно ...

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

Вы также можете уменьшить код и повторение, используя предложение pivot(), если вы используете версию Oracle, которая поддерживает это; который может обеспечить несколько выходов и также позволяет выполнять условное агрегирование:

SELECT *
FROM (
  SELECT
    StoreId,
    Year,
    SUM(AmountSpent) AS TotalSpent
  FROM table_name
  GROUP BY
    StoreId,
    PersonId,
    Year
)
PIVOT (
  SUM(TotalSpent) as total,
  COUNT(CASE WHEN TotalSpent < 100 THEN TotalSpent END) as lt100,
  COUNT(CASE WHEN TotalSpent >= 100 AND TotalSpent < 150 THEN TotalSpent END) as gte100lt150,
  COUNT(CASE WHEN TotalSpent >= 150 THEN TotalSpent END) as gte150
  FOR Year IN (2017 as year17, 2018 as year18)
)
ORDER BY StoreId;

   STOREID YEAR17_TOTAL YEAR17_LT100 YEAR17_GTE100LT150 YEAR17_GTE150 YEAR18_TOTAL YEAR18_LT100 YEAR18_GTE100LT150 YEAR18_GTE150
---------- ------------ ------------ ------------------ ------------- ------------ ------------ ------------------ -------------
         1          145            2                  1             0          200            0                  0             1
         2          200            0                  0             1          330            2                  0             1

Oracle расширит это, чтобы выглядеть как оригинальный более длинный запрос выше, но его легче поддерживать.

Обновлен SQL Fiddle .

0 голосов
/ 11 сентября 2018

Я не думаю, что ваши данные соответствуют ожидаемому результату.

Вам нужен подзапрос, в котором вы суммируете расходы каждого человека в год для каждого магазина (группировка по магазину и человеку).Тогда вам нужно будет группировать только по магазинам и использовать sum для получения дохода за данный год.count + case + distinct - это ключ для подсчета уникальных идентификаторов людей, которые потратили деньги, и назначить их в группу расходов (один из трех столбцов для каждого года).

Обратите внимание, что в столбце yearXX_spending уже содержится сумма суммы, потраченной человеком для данного магазина и года (и это происходит из подзапроса):

select
    storeid
  , sum(year17_spending) as y17_income
  , count(distinct case when year17_spending < 100 then personid end) as y17_spent_below_100
  , count(distinct case when year17_spending between 100 and 150 then personid end) as y17_spent_100_150
  , count(distinct case when year17_spending > 150 then personid end) as y17_spent_above_150
  , sum(year18_spending) as y18_income
  , count(distinct case when year18_spending < 100 then personid end) as y18_spent_below_100
  , count(distinct case when year18_spending between 100 and 150 then personid end) as y18_spent_100_150
  , count(distinct case when year18_spending > 150 then personid end) as y18_spent_above_150
from (
  select 
      storeid
    , personid
    , sum(case when year = 2017 then amountspent end) as year17_spending
    , sum(case when year = 2018 then amountspent end) as year18_spending
  from table_name
  group by storeid, personid
  ) t
group by storeid

Вывод для ваших данных выборки:

+----+---------+------------+---------------------+-------------------+---------------------+---------------------+------------+-------------------+---------------------+
|    | STOREID | Y17_INCOME | Y17_SPENT_BELOW_100 | Y17_SPENT_100_150 | Y17_SPENT_ABOVE_150 | Y18_INCOME | Y18_SPENT_BELOW_100 | Y18_SPENT_100_150 | Y18_SPENT_ABOVE_150 |
+----+---------+------------+---------------------+-------------------+---------------------+------------+---------------------+-------------------+---------------------+
| 1  | 1       | 145        | 2                   | 1                 | 0                   | 200        | 2                   | 0                 | 1                   |
+----+---------+------------+---------------------+-------------------+---------------------+---------------------+------------+-------------------+---------------------+
| 2  | 2       | 200        | 0                   | 0                 | 1                   | 330        | 0                   | 0                 | 1                   |
+----+---------+------------+---------------------+-------------------+---------------------+------------+---------------------+-------------------+---------------------+

Также обратите внимание, что, выполняя UNION при построении образцов данных, вы избавляетесь от дубликатов, поэтому строка:

select 2, 1, 10, 2017

попадает только в таблицуодин раз (не дважды).Если вы хотите включить все без удаления дубликатов, используйте UNION ALL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...