一点儿知识

Posted on May 03, 2022Read on Mirror.xyz

数据 | 数据分析之Dune Analytics(二)

本文参考:https://towardsdatascience.com/your-guide-to-basic-sql-while-learning-ethereum-at-the-same-time-9eac17a05929

我们知道Reserve是Token的合约地址,但是ETH本身没有合约地址,因此我们使用\xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee来作为ETH合约地址。

SELECT * FROM aave."LendingPool_evt_Deposit"
WHERE _reserve = '\xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
limit 10

假设我们现在只需要Dune展示Reserve、user、amount这三个参数,并且合约地址换为USDT,则:

SELECT _reserve, _user, _amount FROM aave."LendingPool_evt_Borrow"
WHERE _reserve = '\xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
limit 5


COUNT, SUM, GROUP BY, HAVING, ORDER BY的使用

1、这里sum表示Aave过去代币质押的总量,count是该合约地址的总交互次数

SELECT SUM(_amount),COUNT(_reserve) FROM aave."LendingPool_evt_Borrow"
WHERE _reserve = '\xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
limit 100

2、_borrowRateMode中1代表浮动利率贷款,2代表固定利率贷款,通过该SQL语句我们可以知道所有的USDT中固定利率与浮动利率贷款的占比大概为10:7,此外,这里的Group BY是将一样的参数放在一起,比如这里将所有的固定利率和浮动利率的合约交互都放在了一起(不理解Group By可以看这里https://www.runoob.com/sql/sql-groupby.html ),后面的数字1代表SELECT后的第一个参数,当我们该为2时,它就对Sum函数进行聚合,但是因为sum函数不具有分类聚合的功能,因此会报错。

SELECT "_borrowRateMode", SUM(_amount) as USDC_total FROM aave."LendingPool_evt_Borrow"
WHERE _reserve = '\xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
GROUP BY 1

3、当WHERE函数后使用了Group By之后,我们就不能再次使用WHERE了,此时我们使用HAVING,它的功能和WHERE相同。

SELECT "_user", SUM(_amount) as USDC_total FROM aave."LendingPool_evt_Borrow"
WHERE _reserve = '\xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
GROUP BY 1
HAVING SUM(_amount) > 1000000
ORDER BY 2 DESC

DISTINCT, COUNT DISTINCT的使用

如果我们想知道Aave用户借用了多少种币,我们可以通过DISTINCT对代币合约地址_reserve进行检测,然后用Count记录总的数量(不能用sum,因为sum求和针对数字,而这里的合约地址是字节型)

SELECT "_user", count (DISTINCT(_reserve)) as "# of different reserve assets" FROM aave."LendingPool_evt_Borrow"
GROUP BY 1
ORDER BY 2 DESC


OUTER (e.g. LEFT) and INNER JOIN的使用

在讲解该部分之前,我们需要知道什么是关联数据,相比于在一个数据表中调用数据,我们更常将相关的数据放入不同的表中来调用,每一个表看成是一个csv文件,每一列(行)都有一个关键词,并且每一列都有固定的数据类型(字符串、整型、布尔型、JSON),每一笔交易都有独特的id,确保每一个数据都是独有的,每一个表都有一个主要的关键词(Primary key)和外部关键词(Foreign key与其它的表格形成联结)。下方就是一个例子,最上方有背景颜色的为外部关键词,其次是主要关键词,再下方是行关键词。

下方是AB联结的7种方式以及它的SQL语句实现方法:

图片中都有对应的SQL执行语句,我们尝试使用其中的INNER JOIN来计算出Aave上大户的ETH总质押量和USDT的总借贷量。

SELECT borrow."_user", borrow.USDC_total_borrowed, deposit.ETH_total_deposited FROM
(SELECT "_user", SUM(_amount) as USDC_total_borrowed FROM aave."LendingPool_evt_Borrow"
WHERE _reserve = '\xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
GROUP BY 1) as borrow
INNER JOIN
(SELECT "_user", SUM(_amount) as ETH_total_deposited FROM aave."LendingPool_evt_Deposit"
WHERE _reserve = '\xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
GROUP BY 1) as deposit
ON borrow."_user"=deposit."_user"
ORDER BY 3 DESC

这里FROM后面的内容将相当于A,INNER JOIN后面的内容相当于B,id即为“_user”,DESC前面讲过是降次排序,而此时的A和B就相当于外部的表,它本身也是一段SQL语句,我们从外部去调用它。


假设我们想查看过去7天USDT每天的借用情况,我们可以采用以下SQL语句,其中的date_trunc函数详细信息可以访问https://docs.microsoft.com/zh-cn/azure/databricks/sql/language-manual/functions/date_trunc ,now() - interval '7 days'是指距离现在时间7天内。

SELECT date_trunc('day', evt_block_time), SUM(_amount) as USDC_total FROM aave."LendingPool_evt_Borrow" as borrow
WHERE borrow.evt_block_time > now() - interval '7 days'
AND _reserve = '\xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
GROUP BY 1


UNION and UNION ALL的使用

首先,我们需要搞懂UNION和UNION ALL的区别,可以访问

https://www.w3school.com.cn/sql/sql_union.asp

假设我们需要比较Compound和Aave大户的USDC借贷数量谁更大,我们可以使用以下SQL语句

SELECT "_user", SUM(_amount) as usdc_borrow, 'aave' as lending_pool FROM aave."LendingPool_evt_Borrow"
WHERE _reserve = '\xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
GROUP BY 1
UNION ALL
SELECT borrower, SUM("borrowAmount") as usdc_borrow, 'comp' as lending_pool FROM compound_v2."cErc20_evt_Borrow"
WHERE contract_address = '\x39aa39c021dfbae8fac545936693ac917d5e7563' --contract address is different because this is cUSDC technically
GROUP BY 1
ORDER BY 2 DESC

公众号:一点儿知识

💡 这里需要注意:在Aave和Compound中,参数的名字不同,如user和borrower,其实指的是同一个东西,但是Dune将其命名为不同的名字,以方便我们进行数据调用,此外,Aave我们用的是USDC的合约地址,而Comp我们实际用的cUSDC的地址,因为在实际使用Comp时借贷出来的是cUSDC.