我希望计算出某年在某家商店花费一定金额的人数。
我尝试制作一个嵌套的CASE表达式,第一个查看某个年份的交易,第二个查看一个人到某个商店的交易总和,但是Oracle不喜欢嵌套的CASE表达式(除非我是做错了)。
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 |
+----+---------+------------+---------------------+-------------------+---------------------+------------+---------------------+-------------------+---------------------+
不确定这是否可行,但是如果可以,那就太好了!
答案 0 :(得分:3)
我认为您的数据与预期输出不符。
您需要一个子查询,您可以在该子查询中汇总每个商店每年每个人的支出(按商店和人分组)。然后,您将仅需要按商店分组并使用sum
来检索给定年份的收入。 count
+ case
+ distinct
是计算花费了钱并将其分配到金额支出组(每年三列之一)的唯一人员ID的关键。
请注意,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
。
答案 1 :(得分:1)
您可以在内联视图中进行商店/人员总计,该视图本身会产生:
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
,然后在外部查询中使用多个单独的case表达式和集合:
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
与您的图像输出不匹配,但是我认为这是错误的...
我也根据您的列标题建议对存储桶进行了一些更改,但是如果您确实想要显示的内容,则可以对其进行调整。
如果您使用的Oracle版本支持,也可以使用pivot()
子句来减少代码和重复。可以提供多个输出并允许有条件的聚合:
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将对其进行扩展,使其看起来像上面的原始较长查询,但更易于维护。