Networking PowerBI/DAX计算列,用于从指定的计算机/网络ip和掩码计算网络CIDR

Networking PowerBI/DAX计算列,用于从指定的计算机/网络ip和掩码计算网络CIDR,networking,powerbi,ip,dax,cidr,Networking,Powerbi,Ip,Dax,Cidr,我的公司服务器上只安装了“基本”PBI,因此我需要找到一个使用DAX或PowerQuery的解决方案。没有Python,没有R…:/ 我有两个带有网络ip和掩码的表,另一个带有机器ip和掩码 我想在这两个表之间建立一个关系 我的想法是在每个表中计算一个新列。 它将是CIDR表示法中的网络ip和掩码, 我将使用它作为建立关系的公用键: 计算机--N:1-->网络 Networks Table == netip, netmask -> netcidr * 10.

我的公司服务器上只安装了“基本”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, b, c, d, "/", cidr)


    #ip, cidr, 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
但它不起作用:

1/我在DAX中找不到位运算符。。。因此,“VAR n1=p1&&ip1”不能作为按位and。是否可以按位和另一种方式执行

2/在DAX中是否有其他方法可以更轻松地执行此操作


3/否则,可以使用PowerQuery实现DAX解决方案,即使最好将此计算移到SQL或Power Query

我想我修复了你代码的最后一步

[cidr_net] =
        // il faut un biwise and de l ip et du mask pour trouver le cidre du reseau ...
        VAR mask = "255.255.255.224"
        VAR dot1 =
            FIND ( ".", mask, 1, 0 )
        VAR p1 =
            VALUE ( IF ( dot1 > 0, ( MID ( mask, 1, dot1 - 1 ) ), "0" ) )
        VAR dot2 =
            FIND ( ".", mask, dot1 + 1, 0 )
        VAR p2 =
            VALUE ( IF ( dot2 > 0, MID ( mask, dot1 + 1, dot2 - 1 - dot1 ), "0" ) )
        VAR dot3 =
            FIND ( ".", mask, dot2 + 1, 0 )
        VAR p3 =
            VALUE ( IF ( dot3 > 0, MID ( mask, dot2 + 1, dot3 - 1 - dot2 ), "0" ) )
        VAR p4 =
            VALUE ( IF ( dot3 > 0, MID ( mask, dot3 + 1, LEN ( mask ) - dot3 ), "0" ) )
        VAR ip = "10.10.1.38"
        VAR d1 =
            FIND ( ".", ip, 1, 0 )
        VAR ip1 =
            VALUE ( IF ( d1 > 0, ( MID ( ip, 1, d1 - 1 ) ), "0" ) )
        VAR d2 =
            FIND ( ".", ip, d1 + 1, 0 )
        VAR ip2 =
            VALUE ( IF ( d2 > 0, MID ( ip, d1 + 1, d2 - 1 - d1 ), "0" ) )
        VAR d3 =
            FIND ( ".", ip, d2 + 1, 0 )
        VAR ip3 =
            VALUE ( IF ( d3 > 0, MID ( ip, d2 + 1, d3 - 1 - d2 ), "0" ) )
        VAR ip4 =
            VALUE ( IF ( d3 > 0, MID ( ip, d3 + 1, LEN ( ip ) - d3 ), "0" ) )
        VAR ipAddress = ( ( ip1 * 256 + ip2 ) * 256 + ip3 ) * 256 + ip4
        VAR ipMask = ( ( p1 * 256 + p2 ) * 256 + p3 ) * 256 + p4
        VAR unmask = 2 ^ 32 - ipMask
        VAR ipNet =
            INT ( ipAddress / unmask ) * unmask
        VAR in1 =
            INT ( ipNet / 2 ^ 24 )
        VAR in2 =
            INT ( MOD ( ipNet, 2 ^ 24 ) / 2 ^ 16 )
        VAR in3 =
            INT ( MOD ( ipNet, 2 ^ 16 ) / 2 ^ 8 )
        VAR in4 =
            MOD ( ipNet, 2 ^ 8 )
        VAR Result =
            in1 & "." & in2 & "." & in3 & "." & in4 & "/"
                & 32 - LOG ( unmask, 2 )
        RETURN
            Result

可以实现DAX解决方案,即使最好将此计算移到SQL或Power Query

我想我修复了你代码的最后一步

[cidr_net] =
        // il faut un biwise and de l ip et du mask pour trouver le cidre du reseau ...
        VAR mask = "255.255.255.224"
        VAR dot1 =
            FIND ( ".", mask, 1, 0 )
        VAR p1 =
            VALUE ( IF ( dot1 > 0, ( MID ( mask, 1, dot1 - 1 ) ), "0" ) )
        VAR dot2 =
            FIND ( ".", mask, dot1 + 1, 0 )
        VAR p2 =
            VALUE ( IF ( dot2 > 0, MID ( mask, dot1 + 1, dot2 - 1 - dot1 ), "0" ) )
        VAR dot3 =
            FIND ( ".", mask, dot2 + 1, 0 )
        VAR p3 =
            VALUE ( IF ( dot3 > 0, MID ( mask, dot2 + 1, dot3 - 1 - dot2 ), "0" ) )
        VAR p4 =
            VALUE ( IF ( dot3 > 0, MID ( mask, dot3 + 1, LEN ( mask ) - dot3 ), "0" ) )
        VAR ip = "10.10.1.38"
        VAR d1 =
            FIND ( ".", ip, 1, 0 )
        VAR ip1 =
            VALUE ( IF ( d1 > 0, ( MID ( ip, 1, d1 - 1 ) ), "0" ) )
        VAR d2 =
            FIND ( ".", ip, d1 + 1, 0 )
        VAR ip2 =
            VALUE ( IF ( d2 > 0, MID ( ip, d1 + 1, d2 - 1 - d1 ), "0" ) )
        VAR d3 =
            FIND ( ".", ip, d2 + 1, 0 )
        VAR ip3 =
            VALUE ( IF ( d3 > 0, MID ( ip, d2 + 1, d3 - 1 - d2 ), "0" ) )
        VAR ip4 =
            VALUE ( IF ( d3 > 0, MID ( ip, d3 + 1, LEN ( ip ) - d3 ), "0" ) )
        VAR ipAddress = ( ( ip1 * 256 + ip2 ) * 256 + ip3 ) * 256 + ip4
        VAR ipMask = ( ( p1 * 256 + p2 ) * 256 + p3 ) * 256 + p4
        VAR unmask = 2 ^ 32 - ipMask
        VAR ipNet =
            INT ( ipAddress / unmask ) * unmask
        VAR in1 =
            INT ( ipNet / 2 ^ 24 )
        VAR in2 =
            INT ( MOD ( ipNet, 2 ^ 24 ) / 2 ^ 16 )
        VAR in3 =
            INT ( MOD ( ipNet, 2 ^ 16 ) / 2 ^ 8 )
        VAR in4 =
            MOD ( ipNet, 2 ^ 8 )
        VAR Result =
            in1 & "." & in2 & "." & in3 & "." & in4 & "/"
                & 32 - LOG ( unmask, 2 )
        RETURN
            Result

我实现了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, '.') ) AS src
PIVOT
(MAX(value) FOR ID in ([1],[2],[3],[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, C.mask, 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, C.mask, 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
这是该代码在上的链接


我认为最好的选择可能是在powerquery中使用M。

我实现了一个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, '.') ) AS src
PIVOT
(MAX(value) FOR ID in ([1],[2],[3],[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, C.mask, 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, C.mask, 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
这是该代码在上的链接


我认为最好的选择可能是在Power查询中使用M。

谢谢您的帮助,我将对其进行测试并给出反馈。如果您在PowerQuery或SQL中有相同的功能,这也会很有用。它非常有用!谢谢我的DAX代码的第一部分看起来很难看……我不知道是否有办法让它更“优雅”,但它的可读代码很容易理解:)谢谢你,我会测试它并给你反馈。如果您在PowerQuery或SQL中有相同的功能,这也会很有用。它非常有用!谢谢我的DAX代码的第一部分看起来很难看……我不知道是否有办法让它更“优雅”,但它的可读代码很容易理解:)谢谢你的代码。它看起来很复杂,但对我来说很有用,因为我使用ip和掩码。谢谢你的代码。它看起来很复杂,但对我来说很有用,因为我使用ip和掩码。