首先,我在SQL上很糟糕,这证明了这一点。最终目标是我有一个数据库(What' s Up Gold),我试图将所有设备导出并在此过程中获得一些关键字段。我可以通过下面的查询获得我想要的所有数据。但是,由于连接,它会返回找到匹配项的重复行。理想情况下,我希望将每个唯一项添加为一列,以便每个设备留下一行,并根据需要添加所有属性,即使它是空的。
SELECT Device.sDisplayName, NetworkInterface.sNetworkAddress, NetworkInterface.sNetworkName, DeviceGroup.sGroupName,
ActiveMonitorType.sMonitorTypeName, ActionPolicy.sPolicyName, Device.sNote , DeviceAttribute.sValue
FROM NetworkInterface join Device ON (NetworkInterface.nDeviceID = Device.nDeviceID)
left outer join dbo.DeviceType on Device.nDeviceTypeID = DeviceType.nDeviceTypeID
left outer join dbo.PivotDeviceToGroup on PivotDeviceToGroup.nDeviceID = Device.nDeviceID
left outer join dbo.DeviceGroup on DeviceGroup.nDeviceGroupID = PivotDeviceToGroup.nDeviceGroupID
left outer join dbo.PivotActiveMonitorTypeToDevice on PivotActiveMonitorTypeToDevice.nDeviceID = Device.nDeviceID
left outer join dbo.ActiveMonitorType on ActiveMonitorType.nActiveMonitorTypeID = PivotActiveMonitorTypeToDevice.nActiveMonitorTypeID
left outer join ActionPolicy ON Device.nActionPolicyID = ActionPolicy.nActionPolicyID
left outer JOIN DeviceAttribute ON Device.nDeviceID = DeviceAttribute.nDeviceID
WHERE Device.bRemoved = 0 AND sMonitorTypename NOT LIKE '%Interface%' ORDER BY sNetworkName
示例返回数据:
sDisplayName sNetworkAddress sGroupName sMonitorTypeName sPolicyName sNote sValue
Portland DCI South 10.0.0.1 Main WAN MAP Ping DCI 10 Gig Alert Added from Discovery on Mon Sep 26 12:46:30 2011 Portland HQ Data Center
Portland DCI South 10.0.0.1 Main WAN MAP Ping DCI 10 Gig Alert Added from Discovery on Mon Sep 26 12:46:30 2011 PDX Data Center 10 Gig DCI South
Portland DCI South 10.0.0.1 Main WAN MAP Ping DCI 10 Gig Alert Added from Discovery on Mon Sep 26 12:46:30 2011 ETH10000-XXXXXXX
Portland DCI South 10.0.0.1 Main WAN MAP Ping DCI 10 Gig Alert Added from Discovery on Mon Sep 26 12:46:30 2011 CenturyLink - 1-888-345-4762 option 2
我希望看到的是sValue
列中的每个唯一商品都会以sValue1
sValue2
等方式返回。这样我就离开了每个唯一网络设备使用一行,sNetworkAddress
字段使其唯一。
所需的查询输出:
sDisplayName sNetworkAddress sGroupName sMonitorTypeName sPolicyName sNote sValue1 sValue2 sValue3 sValue4
Portland DCI South 10.0.0.1 Main WAN MAP Ping DCI 10 Gig Alert Added from Discovery on Mon Sep 26 12:46:30 2011 Portland HQ Data Center PDX Data Center 10 Gig DCI South ETH10000-XXXXXXX CenturyLink - 1-888-345-4762 option 2
SELECT d.sDisplayName
, ni.sNetworkAddress
, ni.sNetworkName
, d.sNote
, da.sValue
FROM NetworkInterface ni
INNER join Device d ON ni.nDeviceID = d.nDeviceID
AND d.bRemoved = 0
left outer join dbo.PivotDeviceToGroup pdg on pdg.nDeviceID = d.nDeviceID
left outer join dbo.DeviceGroup dg on dg.nDeviceGroupID = pdg.nDeviceGroupID
left outer join dbo.PivotActiveMonitorTypeToDevice pamtd on pamtd.nDeviceID = d.nDeviceID
left outer join dbo.ActiveMonitorType amt on amt.nActiveMonitorTypeID = pamtd.nActiveMonitorTypeID
AND amt.sMonitorTypename NOT LIKE '%Interface%'
left outer join ActionPolicy ap ON ap.nActionPolicyID = d.nActionPolicyID
left outer JOIN DeviceAttribute da ON da.nDeviceID = d.nDeviceID
ORDER BY ni.sNetworkName
SELECT d.sDisplayName
, ni.sNetworkAddress
, ni.sNetworkName
, d.sNote
, da.sValue
INTO #TEMP
FROM NetworkInterface ni
INNER join Device d ON ni.nDeviceID = d.nDeviceID
AND d.bRemoved = 0
left outer join dbo.PivotDeviceToGroup pdg on pdg.nDeviceID = d.nDeviceID
left outer join dbo.DeviceGroup dg on dg.nDeviceGroupID = pdg.nDeviceGroupID
left outer join dbo.PivotActiveMonitorTypeToDevice pamtd on pamtd.nDeviceID = d.nDeviceID
left outer join dbo.ActiveMonitorType amt on amt.nActiveMonitorTypeID = pamtd.nActiveMonitorTypeID
AND amt.sMonitorTypename NOT LIKE '%Interface%'
left outer join ActionPolicy ap ON ap.nActionPolicyID = d.nActionPolicyID
left outer JOIN DeviceAttribute da ON da.nDeviceID = d.nDeviceID
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.sValue)
FROM #TEMP c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT sDisplayName, sNetworkAddress, sNote' + @cols + ' from
(
SELECT
DisplayName
,sNetworkAddress
,sNetworkName
,sNote
,sValue
from temp
) x
pivot
(
max(sNote)
for sValue in (' + @cols + ')
) p '
execute(@query)
drop table #TEMP
返回错误:
(2195 row(s) affected)
Msg 1038, Level 15, State 4, Line 11
An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name.
Msg 1038, Level 15, State 4, Line 53
An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name.
答案 0 :(得分:0)
这里需要的是一个数据透视表。
如果每个项目在查询中返回的记录数量相同,或者您知道可能的最大值,则可以使用简单的数据透视表。但是,如果您有最大未知记录数,则需要使用动态数据透视表。
这是指向此网站上另一个问题的链接,其中显示了如何创建动态数据透视表:SQL Server dynamic PIVOT query?
SELECT d.sDisplayName
, ni.sNetworkAddress
, ni.sNetworkName
, d.sNote
, da.sValue
INTO #TEMP
FROM NetworkInterface ni
INNER join Device d ON ni.nDeviceID = d.nDeviceID
AND d.bRemoved = 0
left outer join dbo.PivotDeviceToGroup pdg on pdg.nDeviceID = d.nDeviceID
left outer join dbo.DeviceGroup dg on dg.nDeviceGroupID = pdg.nDeviceGroupID
left outer join dbo.PivotActiveMonitorTypeToDevice pamtd on pamtd.nDeviceID = d.nDeviceID
left outer join dbo.ActiveMonitorType amt on amt.nActiveMonitorTypeID = pamtd.nActiveMonitorTypeID
AND amt.sMonitorTypename NOT LIKE '%Interface%'
left outer join ActionPolicy ap ON ap.nActionPolicyID = d.nActionPolicyID
left outer JOIN DeviceAttribute da ON da.nDeviceID = d.nDeviceID
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.sValue)
FROM temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT sDisplayName, sNetworkAddress, sNote' + @cols + ' from
(
SELECT
DisplayName
,sNetworkAddress
,sNetworkName
,sNote
,sValue
from temp
) x
pivot
(
max(sNote)
for sValue in (' + @cols + ')
) p '
execute(@query)
drop table temp
答案 1 :(得分:0)
您的设备似乎有多个DeviceAttribute.sValues。因此,您的重复行是与您的设备关联的其他行。
一些建议/说明:
1)为了便于阅读,请为表格添加别名。
2)在JOIN条件下保持一致。有些是ON x = y,有些是ON y = x。它会更容易看到你实际上正在加入的东西。
3)将您的WHERE条件移动到与其关联的JOIN中。如果您在JOERE中的WHERE vs中进行过滤,则可能会得到不一致的结果。
4)双击PivotDeviceToGroup / DeviceGroup和PivotActiveMonitorTypeToDevice / ActiveMonitorType的JOIN组。他们回来了你期望他们返回的东西吗?由于两者都是双LEFT JOIN,因此您将返回pdtg中与pamtd中的dg和行不匹配的行,这些行与amt LIKE'%Interface%',amt data为NULL。
示例:
SELECT d.sDisplayName
, ni.sNetworkAddress
, ni.sNetworkName
, dg.sGroupName
, amt.sMonitorTypeName
, ap.sPolicyName
, d.sNote
, da.sValue
FROM NetworkInterface ni
INNER join Device d ON ni.nDeviceID = d.nDeviceID
AND d.bRemoved = 0
-- left outer join dbo.DeviceType dt on dt.nDeviceTypeID = d.nDeviceTypeID --- <<< You aren't using this table. Can you remove the JOIN?
left outer join dbo.PivotDeviceToGroup pdg on pdg.nDeviceID = d.nDeviceID
left outer join dbo.DeviceGroup dg on dg.nDeviceGroupID = pdg.nDeviceGroupID
left outer join dbo.PivotActiveMonitorTypeToDevice pamtd on pamtd.nDeviceID = d.nDeviceID
left outer join dbo.ActiveMonitorType amt on amt.nActiveMonitorTypeID = pamtd.nActiveMonitorTypeID
AND amt.sMonitorTypename NOT LIKE '%Interface%'
left outer join ActionPolicy ap ON ap.nActionPolicyID = d.nActionPolicyID
left outer JOIN DeviceAttribute da ON da.nDeviceID = d.nDeviceID
编辑:这很快就会成为一个相当复杂的PIVOT。但玩起来很有趣。我没有任何数据可以测试,但看看这样的东西是否有效。
DECLARE @colNames nvarchar(max)
, @query nvarchar(max)
DECLARE @tq1 TABLE (
sDisplayName varchar(max)
, sNetworkAddress varchar(max)
, sNetworkName varchar(max)
, sGroupName varchar(max)
, sMonitorType varchar(max)
, sPolicyName varchar(max)
, sNote varchar(max)
, sValue varchar(max)
)
INSERT INTO @tq1
SELECT d.sDisplayName
, ni.sNetworkAddress
, ni.sNetworkName
, dg.sGroupName
, amt.sMonitorType
, ap.sPolicyName
, d.sNote
, da.sValue
FROM dbo.Device d
INNER JOIN dbo.NetworkInterface ni ON ni.nDeviceID = d.nDeviceID
LEFT OUTER JOIN dbo.PivotDeviceToGroup pdg ON pdg.nDeviceID = d.nDeviceID
INNER JOIN dbo.DeviceGroup dg ON dg.nDeviceGroupID = pdg.nDeviceGroupID
LEFT OUTER JOIN dbo.PivotActiveMonitorTypeToDevice pamtd ON pamtd.nDeviceID = d.nDeviceID
INNER join dbo.ActiveMonitorType amt on amt.nActiveMonitorTypeID = pamtd.nActiveMonitorTypeID
AND amt.sMonitorTypename NOT LIKE '%Interface%'
LEFT OUTER JOIN dbo.ActionPolicy ap ON ap.nActionPolicyID = d.nActionPolicyID
LEFT JOIN DeviceAttribute da ON d.nDeviceID = da.nDeviceID
WHERE d.bRemoved = 0
SELECT @colNames = STUFF( (SELECT DISTINCT ',' + QUOTENAME(sValue) FROM @tq1 FOR XML PATH(''), TYPE ).value('.','nvarchar(max)'),1,1,'' )
SET @query = 'SELECT * FROM
(
SELECT sDisplayName
, sNetworkAddress
, sNetworkName
, sGroupName
, sMonitorType
, sPolicyName
, sNote
, sValue
FROM @tq1
) t1
PIVOT
(
max(sValue) FOR sValue IN (' + @colNames + ')
) p
ORDER BY sNetworkName
'
EXECUTE ( @query )