问题描述
我的公司服务器上只安装了“基本”PBI,因此我需要使用 DAX 或 PowerQuery 找到解决方案。没有 Python,没有 R ... :/
我有两个包含网络 ip 和掩码的表,另一个包含机器 ip 和掩码。
我想设置两个表之间的关系。
我的想法是在每个表中计算一个新列。 它将是 CIDR 表示法中的网络 ip 和掩码, 我将使用它作为建立关系的常用键:
机器 --N:1--> 网络
Networks Table
==
netip,netmask -> netcidr *
10.10.1.32,255.255.255.224 -> 10.10.1.32/27
Machines Table
==
machineip,netmask -> netcidr *
10.10.1.35,255.255.255.224 -> 10.10.1.32/27
10.10.1.38,255.255.255.224 -> 10.10.1.32/27
- 在这两种情况下,我都需要计算 netcidr 列。
我已经用 Python 函数完成了它,但我需要在 DAX、PowerQuery 或 sql 中进行转换:
def network2(ipmask):
ip,cidr = ipmask.split('/')
print(">",ip,cidr)
a,b,c,d = ip.split('.')
ipn = (((int(a)*256+int(b))*256)+int(c))*256+int(d)
cidr = int(cidr)
mask = (0xffffffff >> (32 - cidr)) << (32 - cidr)
net = ipn & mask
print (ipn,cidr,mask,net )
a = net%(256**4)//(256**3)
b = net%(256**3)//(256**2)
c = net%(256**2)//(256**1)
d = net%(256**1)//(256**0)
#net IP decimal
print(">>>old - ip: ",ipmask)
print(">>>nets - ip: ",a,d,"/",cidr)
#ip,mask
# for i in ip.split('.')
network2('10.10.1.32/27') #mask 255.255.255.224
network2('10.10.1.38/27')
>>>old - ip: 10.10.1.32/27
>>>nets - ip: 10 10 1 32 / 27
>>>old - ip: 10.10.1.38/27
>>>nets - ip: 10 10 1 32 / 27
它在 Python 中工作,现在我尝试在 DAX 中完成:
cidr_net =
// ...
VAR mask = data[mask_lan]
VAR dot1 = FIND(".",1,0)
VAR p1 = VALUE(IF(dot1>0,(MID(mask,dot1-1)),"0"))
VAR dot2 = FIND(".",dot1+1,0)
VAR p2 = VALUE(IF(dot2>0,MID(mask,dot2-1-dot1),"0"))
VAR dot3 = FIND(".",dot2+1,0)
VAR p3 = VALUE(IF(dot3>0,dot3-1-dot2),"0"))
VAR p4 = VALUE(IF(dot3>0,dot3+1,len(mask)-dot3),"0"))
VAR ip = data[ip_lan]
VAR d1 = FIND(".",0)
VAR ip1 = VALUE(IF(d1>0,(MID(ip,d1-1)),"0"))
VAR d2 = FIND(".",d1+1,0)
VAR ip2 = VALUE(IF(d2>0,MID(ip,d2-1-d1),"0"))
VAR d3 = FIND(".",d2+1,0)
VAR ip3 = VALUE(IF(d3>0,d3-1-d2),"0"))
VAR ip4 = VALUE(IF(d3>0,d3+1,len(ip)-d3),"0"))
VAR n1 = p1 && ip1
VAR n2 = p2 && ip2
VAR n3 = p3 && ip3
VAR n4 = p4 && ip4
VAR cidr = FORMAT( 32-log( 4294967296-((((p1*256+p2)*256)+p3)*256+p4),2),"##")
RETURN CONCATENATE(CONCATENATE(CONCATENATE(CONCATENATE(CONCATENATE(CONCATENATE(CONCATENATE(CONCATENATE(n1,"."),n2),n3),n4),"/"),cidr)
但它不起作用:
1/ 我在 DAX 中找不到按位运算符......所以“VAR n1 = p1 && ip1”不能作为按位和。是否可以按位和另一种方式进行?
2/ 在 DAX 中有没有其他方法可以更轻松地做到这一点?
3/ 否则可以使用 PowerQuery 吗?
解决方法
可以实施 DAX 解决方案,即使将此计算移至 SQL 或 Power Query 会更好
我想我修正了你代码的最后一步
docker run -p 8080:8080 -p 50000:50000 -d -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts
this is a link to a working version of this code on DAX.do
,我实现了一个 T-SQL 版本的转换。它使用 STRING_SPLIT() 函数,该函数自 SQL Server 2016 起可用。它非常复杂,而且从性能的角度来看也可能很糟糕。我不会在生产中使用它,但只是为了在这里了解它
首先我创建一个示例表
create table t( ip varchar(40) not null,mask varchar(40) not null);
insert into t(ip,mask) values ('10.0.1.38','255.255.255.224');
然后查询
WITH CTE AS (
SELECT ip,mask,B.ipn,M.masknc
from t AS A
CROSS APPLY (
SELECT (([1] * 256 + [2]) * 256 + [3]) * 256 + [4] AS ipn FROM
(SELECT CAST([value] AS BIGINT) AS value,ID = ROW_NUMBER() OVER(ORDER BY(SELECT NULL))
FROM STRING_SPLIT(A.ip,'.') ) AS src
PIVOT
(MAX(value) FOR ID in ([1],[2],[3],[4]) ) AS P ) AS B
CROSS APPLY (
SELECT CAST(256 AS BIGINT) * 256 * 256 * 256 - ((([1] * 256 + [2]) * 256 + [3]) * 256 + [4]) AS masknc FROM
(SELECT CAST([value] AS BIGINT) AS value,ID = ROW_NUMBER() OVER(ORDER BY(SELECT NULL))
FROM STRING_SPLIT(A.mask,[4]) ) AS P ) AS M
),CTE1 AS (
SELECT C.ip,C.mask,CAST(C.ipn / C.masknc AS BIGINT) * C.masknc AS netipn,32 - LOG(C.masknc,2) AS maskc,E32 = CAST(256 AS BIGINT) * 256 * 256 * 256,E24 = CAST(256 AS BIGINT) * 256 * 256,E16 = CAST(256 AS BIGINT) * 256,E8 = CAST(256 AS BIGINT)
FROM CTE AS C
),CTE2 AS (
SELECT C.ip,netip1 = FLOOR(netipn / E24),netip2 = FLOOR((netipn % E24)/ E16),netip3 = FLOOR((netipn % E16) / E8),netip4 = FLOOR(netipn % E8),C.maskc
FROM CTE1 AS C
)
SELECT C.ip,CAST(C.netip1 AS VARCHAR(3)) + '.' + CAST(C.netip2 AS VARCHAR(3)) + '.' +
CAST(C.netip3 AS VARCHAR(3)) + '.' + CAST(C.netip4 AS VARCHAR(3)) + '/' + CAST(C.maskc AS VARCHAR(4)) AS netip
FROM CTE2 AS C
这是此代码在 dbfiddle.uk 上的链接
我认为最好的选择可能是在 Power Query 中使用 M。