我们可以按日期汇总,分别统计每天生成的区块数量和对应的Gas消耗。为了跟踪变化趋势,我们首先定义一个CTE来完成每日数据统计,然后在此CTE基础上,使用avg(blocks_count) over (order by rows between 6 preceding and current row)这样的窗口函数来统计7天的移动平均值。SQL如下:
with block_daily as (
select date_trunc('day', time) as block_date,
count(*) as blocks_count,
sum(gas_used * coalesce(base_fee_per_gas, 1)) / 1e18 as gas_used
from polygon.blocks
group by 1
)
select block_date,
blocks_count,
gas_used,
avg(blocks_count) over (order by block_date rows between 6 preceding and current row) as ma_7_days_blocks_count,
avg(blocks_count) over (order by block_date rows between 29 preceding and current row) as ma_30_days_blocks_count,
avg(gas_used) over (order by block_date rows between 6 preceding and current row) as ma_7_days_gas_used
from block_daily
order by block_date
with transactions_detail as (
select block_time,
hash,
"from" as address
from polygon.transactions
union all
select block_time,
hash,
"to" as address
from polygon.transactions
)
select count(distinct hash) / 1e6 as transactions_count,
count(distinct address) / 1e6 as users_count
from transactions_detail
with transactions_detail as (
select block_time,
hash,
"from" as address
from polygon.transactions
union all
select block_time,
hash,
"to" as address
from polygon.transactions
)
select date_trunc('day', block_time) as block_date,
count(distinct hash) as transactions_count,
count(distinct address) as users_count
from transactions_detail
group by 1
order by 1
with users_details as (
select block_time,
"from" as address
from polygon.transactions
union all
select block_time,
"to" as address
from polygon.transactions
),
users_initial_transaction as (
select address,
min(date_trunc('day', block_time)) as min_block_date
from users_details
group by 1
),
new_users_daily as (
select min_block_date as block_date,
count(address) as new_users_count
from users_initial_transaction
group by 1
),
active_users_daily as (
select date_trunc('day', block_time) as block_date,
count(distinct address) as active_users_count
from users_details
group by 1
)
select u.block_date,
active_users_count,
coalesce(new_users_count, 0) as new_users_count,
active_users_count - coalesce(new_users_count, 0) as existing_users_count
from active_users_daily u
left join new_users_daily n on u.block_date = n.block_date
order by u.block_date
select date_trunc('day', minute) as block_date,
avg(price) as price
from prices.usd
where blockchain = 'polygon'
and symbol = 'MATIC'
group by 1
order by 1
with polygon_transfer_raw as (
select "from" as address, (-1) * cast(value as decimal) as amount
from polygon.traces
where call_type = 'call'
and success = true
and value > uint256 '0'
union all
select "to" as address, cast(value as decimal) as amount
from polygon.traces
where call_type = 'call'
and success = true
and value > uint256 '0'
)
select address,
sum(amount) / 1e18 as amount
from polygon_transfer_raw
group by 1
order by 2 desc
limit 1000
上面查询中的注意事项:polygon.traces表中的value字段是uint256类型,这是Dune SQL自定义的类型,如果直接和数值0进行比较将会遇到类型不匹配不能比较的错误。所以我们用uint256 '0'这样的语法将数值0转换为相同类型再比较。也可以用cast(0 as uint256)这样的类型转换函数。当然也可以把value的值转换为double、decimal、bigint等再比较,但是此时需要注意可能出现数据溢出的问题。
with polygon_transfer_raw as (
-- same as above
),
polygon_top_holders as (
select address,
sum(amount) / 1e18 as amount
from polygon_transfer_raw
group by 1
order by 2 desc
limit 1000
)
select (case when amount >= 10000000 then '>= 10M'
when amount >= 1000000 then '>= 1M'
when amount >= 500000 then '>= 500K'
when amount >= 100000 then '>= 100K'
else '< 100K'
end) as amount_segment,
count(*) as holders_count
from polygon_top_holders
group by 1
order by 2 desc
为以上两个查询分别生成 Bar Chart 和 Pie Chart 可视化图表。加入数据看板,显示效果如下:
查询链接:
智能合约分析
创建和已销毁的合约数量
select type,
count(*) / 1e6 as transactions_count
from polygon.traces
where type in ('create', 'suicide')
and block_time >= date('2023-01-01') -- 这里为了性能考虑加了日期条件
group by 1
order by 1
我们可以按日期统计新创建和已销毁的合约数量。考虑到累计数量也比较有参考价值,我们先用一个CTE统计出每日数据,然后使用窗口函数sum() over (partition by type order by block_date)来统计按日期累计的总数。其中的partition by type用于指定按类型分别汇总。
with polygon_contracts as (
select date_trunc('day', block_time) as block_date,
type,
count(*) as transactions_count
from polygon.traces
where type in ('create', 'suicide')
group by 1, 2
)
select block_date,
type,
transactions_count,
sum(transactions_count) over (partition by type order by block_date) as accumulate_transactions_count
from polygon_contracts
order by block_date
with contract_summary as (
select "to" as contract_address,
count(*) as transaction_count
from polygon.transactions
where success = true
group by 1
order by 2 desc
limit 100
)
select contract_address,
'<a href=https://polygonscan.com/address/' || cast(contract_address as varchar) || ' target=_blank>PolygonScan</a>' as link,
transaction_count
from contract_summary
order by transaction_count desc
with top_contracts as (
select "to" as contract_address,
count(*) as transaction_count
from polygon.transactions
where success = true
group by 1
order by 2 desc
limit 20
)
select date_trunc('day', block_time) as block_date,
contract_address,
count(*) as transaction_count
from polygon.transactions t
inner join top_contracts c on t."to" = c.contract_address
group by 1, 2
order by 1, 2
select "to" as contract_address,
'<a href=https://polygonscan.com/address/' || cast("to" as varchar) || ' target=_blank>PolygonScan</a>' as link,
count(*) as transaction_count
from polygon.transactions
where block_time >= now() - interval '30' day
group by 1, 2
order by 3 desc
limit 50