使用Power BI DAX实现动态城市的50英里内取货地点查询
解决Power BI中基于动态城市/州查询50英里半径内取货点的问题
问题背景
我需要在Power BI里实现:根据用户选择的美国城市、州(对应tableB里的经纬度),列出该地点50英里范围内的tableA取货点。之前尝试的度量值只能返回总计距离,没法逐个展示每个取货点到选中城市的距离;另一个计算列是基于同表内的经纬度做计算,不符合跨表动态起点的需求。
解决方案步骤
1. 调整数据模型
确保tableB(存储美国城市经纬度,字段包含城市、州、lat、lng)和tableA(存储取货点经纬度)没有建立直接关联——因为要支持动态选择起点,固定关联会限制灵活性,且每个城市的经纬度要保证唯一。
2. 创建动态距离度量值
要实现逐个取货点计算距离,不能用MIN这类聚合函数去取tableA的经纬度,得用迭代函数(比如SUMX)遍历tableA每一行,计算单个取货点到选中城市的距离。下面是两种可行的DAX写法:
写法1:基于Haversine公式(直接计算英里)
到选中城市的距离(英里)= VAR 选中城市纬度 = SELECTEDVALUE('tableB'[lat]) VAR 选中城市经度 = SELECTEDVALUE('tableB'[lng]) VAR 弧度转换 = DIVIDE(PI(), 180) RETURN SUMX( 'tableA', VAR 取货点纬度弧度 = 'tableA'[lat] * 弧度转换 VAR 取货点经度弧度 = 'tableA'[lng] * 弧度转换 VAR 选中城市纬度弧度 = 选中城市纬度 * 弧度转换 VAR 选中城市经度弧度 = 选中城市经度 * 弧度转换 VAR 纬度差 = 取货点纬度弧度 - 选中城市纬度弧度 VAR 经度差 = 取货点经度弧度 - 选中城市经度弧度 VAR a = SIN(纬度差/2)^2 + COS(选中城市纬度弧度) * COS(取货点纬度弧度) * SIN(经度差/2)^2 VAR c = 2 * ASIN(MIN(SQRT(a), 1)) // 避免数值溢出导致的计算错误 RETURN 3959 * c // 3959为地球半径(英里),弧度值转实际英里距离 )
写法2:先算公里再转英里的Haversine实现
到选中城市的距离(英里)= VAR 选中城市纬度 = SELECTEDVALUE('tableB'[lat]) VAR 选中城市经度 = SELECTEDVALUE('tableB'[lng]) VAR 弧度转换 = DIVIDE(PI(), 180) RETURN SUMX( 'tableA', VAR 取货点纬度 = 'tableA'[lat] VAR 取货点经度 = 'tableA'[lng] VAR 纬度差弧度 = (取货点纬度 - 选中城市纬度) * 弧度转换 VAR 经度差弧度 = (取货点经度 - 选中城市经度) * 弧度转换 VAR 中间值 = 0.5 - COS(纬度差弧度)/2 + COS(选中城市纬度 * 弧度转换) * COS(取货点纬度 * 弧度转换) * (1 - COS(经度差弧度))/2 VAR 距离公里 = 12742 * ASIN(SQRT(中间值)) // 12742为地球直径(公里) RETURN 距离公里 * 0.621371 // 公里转英里的转换系数 )
3. 添加筛选逻辑
创建一个用于筛选的度量值,标记出50英里内的取货点:
在50英里范围内 = IF( [到选中城市的距离(英里)] <= 50, 1, 0 )
4. 配置可视化
- 插入表格可视化,添加
tableA的取货点名称、地址等需要展示的字段 - 添加「到选中城市的距离(英里)」度量值,设置格式为保留1-2位小数
- 添加筛选器,设置「在50英里范围内」等于1
- 插入切片器,选择
tableB的城市/州字段,用户选择后即可动态展示符合条件的取货点
为什么之前的度量值只返回总计?
之前的度量值用了MIN('tableA'[lat])和MIN('tableA'[lng]),这会直接聚合整个tableA的经纬度数据,只返回一组最小经纬度对应的距离,而不是逐个计算每个取货点的距离。用SUMX这类迭代函数可以遍历tableA每一行,对单个取货点做距离计算,最终返回每个点的对应值。
内容的提问来源于stack exchange,提问作者pbi_user4257920
相关产品推荐
相关产品推荐

