Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将多个SQL行转换为一行_Sql_Sql Server_Sql Server 2008 - Fatal编程技术网

将多个SQL行转换为一行

将多个SQL行转换为一行,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,下午好,人们的堆栈溢出 我正在尝试做一些我不确定如何用我的SQL知识来实现的事情,但是我很清楚我想要从中得到什么,所以希望这对人们来说是有意义的 我有一些perfmon磁盘结果,如下所示: DatabaseName ObjectName CounterName InstanceName Server Average DAG1DB01 logicaldisk avg. disk sec/read d:\

下午好,人们的堆栈溢出

我正在尝试做一些我不确定如何用我的SQL知识来实现的事情,但是我很清楚我想要从中得到什么,所以希望这对人们来说是有意义的

我有一些perfmon磁盘结果,如下所示:

DatabaseName    ObjectName      CounterName         InstanceName                Server      Average
DAG1DB01        logicaldisk     avg. disk sec/read  d:\mountpoints\DAG1DB01     Server1     13.616
DAG1DB01        logicaldisk     avg. disk sec/read  d:\mountpoints\DAG1DB01     Server2     17.508
DAG1DB01        logicaldisk     avg. disk sec/read  d:\mountpoints\DAG1DB01     Server3     12.775
DAG1DB01        logicaldisk     avg. disk sec/read  d:\mountpoints\DAG1DB01     Server4     13.148
DAG1DB01        logicaldisk     avg. disk sec/read  d:\mountpoints\DAG1DB01     Server5     10.091
FROM E14_Databases AS e14_db
INNER JOIN E14_Perfmon_MBX AS server1
ON e14_db.LogFolderPath = server1.InstanceName 
AND server1.Server = 'Server1'
AND server1.ObjectName = 'logicaldisk'
AND server1.CounterName = 'avg. disk sec/read'
AND server1.DateTime > (DATEADD(hh, -4, GETDATE()))
AND server1.Value < 1
INNER JOIN E14_Perfmon_MBX AS server2
ON e14_db.LogFolderPath = server2.InstanceName 
AND server2.Server = 'Server2'
AND server2.ObjectName = 'logicaldisk'
AND server2.CounterName = 'avg. disk sec/read'
AND server2.DateTime > (DATEADD(hh, -4, GETDATE()))
AND server2.Value < 1
以下是基于此查询的示例行:

SELECT
e14_db.DatabaseName AS [DatabaseName],
d.ObjectName,
d.CounterName,
d.InstanceName,
d.Server,
AVG(Value) * 1000 AS [Average]
FROM E14_Perfmon_MBX AS d
INNER JOIN E14_Databases AS e14_db
ON e14_db.LogFolderPath = d.InstanceName
WHERE d.ObjectName = 'logicaldisk'
AND d.CounterName = 'avg. disk sec/read'
AND d.DateTime > (DATEADD(hh, -4, GETDATE()))
AND d.Value < 1
GROUP BY d.ObjectName, d.CounterName, d.InstanceName, d.Server, e14_db.DatabaseName
ORDER BY e14_db.DatabaseName, d.Server
有人知道我怎样才能做到这一点吗?基本上是将行应用到自己身上

如果需要任何澄清,请随时询问


谢谢

修改该表以包含额外的列,并运行更新,其中server='Server2'

更新d set server2=上一个服务器条目的值,其中server='server2'例如

这样做很痛苦,但唯一的其他选择是在不使用SQL语句的情况下对表进行物理编辑


编辑:我建议创建两个表,一个包含关于it数据库名称等的所有信息,另一个包含分数,尝试为每个服务器连接一次PERFMON表,如下所示:

DatabaseName    ObjectName      CounterName         InstanceName                Server      Average
DAG1DB01        logicaldisk     avg. disk sec/read  d:\mountpoints\DAG1DB01     Server1     13.616
DAG1DB01        logicaldisk     avg. disk sec/read  d:\mountpoints\DAG1DB01     Server2     17.508
DAG1DB01        logicaldisk     avg. disk sec/read  d:\mountpoints\DAG1DB01     Server3     12.775
DAG1DB01        logicaldisk     avg. disk sec/read  d:\mountpoints\DAG1DB01     Server4     13.148
DAG1DB01        logicaldisk     avg. disk sec/read  d:\mountpoints\DAG1DB01     Server5     10.091
FROM E14_Databases AS e14_db
INNER JOIN E14_Perfmon_MBX AS server1
ON e14_db.LogFolderPath = server1.InstanceName 
AND server1.Server = 'Server1'
AND server1.ObjectName = 'logicaldisk'
AND server1.CounterName = 'avg. disk sec/read'
AND server1.DateTime > (DATEADD(hh, -4, GETDATE()))
AND server1.Value < 1
INNER JOIN E14_Perfmon_MBX AS server2
ON e14_db.LogFolderPath = server2.InstanceName 
AND server2.Server = 'Server2'
AND server2.ObjectName = 'logicaldisk'
AND server2.CounterName = 'avg. disk sec/read'
AND server2.DateTime > (DATEADD(hh, -4, GETDATE()))
AND server2.Value < 1

请查看此链接中所示的透视表语法

这将允许你做你要求的事情。请务必查看动态生成列标题的部分。

该操作符专为此类场景设计。这将为您提供您想要的:

SELECT DatabaseName, 
    ObjectName, 
    CounterName, 
    InstanceName, 
    Server1, 
    Server2, 
    Server3, 
    Server4, 
    Server5 
FROM (SELECT
        e14_db.DatabaseName AS [DatabaseName],
        d.ObjectName,
        d.CounterName,
        d.InstanceName,
        d.[Server],
        d.Value * 1000 AS [Value]
    FROM E14_Perfmon_MBX AS d
        INNER JOIN E14_Databases AS e14_db
            ON e14_db.LogFolderPath = d.InstanceName
    WHERE d.ObjectName = 'logicaldisk'
        AND d.CounterName = 'avg. disk sec/read'
        AND d.DateTime > (DATEADD(hh, -4, GETDATE()))
        AND d.Value < 1) sub
PIVOT
(
    AVG(Value)
    FOR [Server] IN ([Server1], [Server2], [Server3], [Server4], [Server5])
) AS PivotTable

以下语句以固定的列数(从1到5)计算每个服务器的单独平均值:

SELECT e14_db.DatabaseName AS [DatabaseName]
, d.ObjectName, d.CounterName, d.InstanceName
, AVG(CASE WHEN d.Server = 'Server1' THEN Value ELSE NULL END) *1000 AS [Server1]
, AVG(CASE WHEN d.Server = 'Server2' THEN Value ELSE NULL END) *1000 AS [Server2]
, AVG(CASE WHEN d.Server = 'Server3' THEN Value ELSE NULL END) *1000 AS [Server3]
, AVG(CASE WHEN d.Server = 'Server4' THEN Value ELSE NULL END) *1000 AS [Server4]
, AVG(CASE WHEN d.Server = 'Server5' THEN Value ELSE NULL END) *1000 AS [Server5]
FROM E14_Perfmon_MBX AS d
INNER JOIN E14_Databases AS e14_db
ON e14_db.LogFolderPath = d.InstanceName
WHERE d.ObjectName = 'logicaldisk'
AND d.CounterName = 'avg. disk sec/read'
AND d.DateTime > (DATEADD(hh, -4, GETDATE()))
AND d.Value < 1
GROUP BY d.ObjectName, d.CounterName, d.InstanceName, e14_db.DatabaseName
ORDER BY e14_db.DatabaseName
您也可以使用PIVOT,但这种语法受到更广泛的SQL风格的支持。

方法1

方法2


-这是一个可怕的建议。首先,它违反了良好的规范化实践——在某些情况下,这应该被违反,但我怀疑这是其中之一。其次,对维护来说很糟糕,如果他添加另一台服务器会发生什么?。第三,理智地提问也非常困难。@X-Zero我编辑了我推荐的答案。我觉得我不应该因为回答手头的问题而被否决。这不是一个好的做法,但他要求原谅的是,他已经有了两张表,其中一张表是分数,修改它不会真正产生好的效果。你不会因为“话题偏离”而被否决——你被否决了,因为我认为答案是“无用的”或者潜在的“危险”。OP特别询问如何以给定的格式检索结果行,这不需要修改表。现在,如果问题包括关于性能差/运行时间长的注释,并且被认为仅用于分析目的,那么您的建议具有优点,因为OLAP角色中的新表会慢慢改变维度。不过,它最初的加载和维护方式可能与其他一些答案类似,这方面的例子很多。只需使用sql server和Pivot搜索@HungryHippos的可能副本-我的帖子中缺少了什么?这是可行的,尽管您至少应该使用CTE来执行一些基本的初始限制/聚合,并且只执行连接以获取单个列。然而,正如许多其他答案所指出的,SQL Server具有为您实现这一点的内置功能。您能否总结一下这一点如何适用于OPs案例?你知道提出这个建议很好,但是试着用一个例子来说明这个问题。这个对我最有效,我也最了解它。感谢所有人的建议,我认为如果我能正确地理解PIVOT,PIVOT也会起作用,但这需要0秒来执行,所以我对我获得的性能感到满意!
declare @Servers varchar(1000) = ''
declare @Query varchar(8000) = ''


select @Servers = ISNULL(QuoteName(Server) + ',', '') + @Servers from MyTable

set @Servers = SUBSTRING(@Servers,0,len(@Servers))

Set @Query = 'Select DatabaseName, obectName, CounterName, InstanceName , ' + 
@Servers + ' From 
(
    Select DatabaseName, obectName, CounterName, InstanceName, 
    Server, Average from Mytable
)K Pivot
(
    max(Average) FOR Server IN (' + @Servers + ')
) AS pvt'

EXEC(@Query)
Select DatabaseName, obectName, CounterName, InstanceName , Server1, Server2, 
Server3, Server4, Server5
From 
(
    Select Select DatabaseName, obectName, CounterName, InstanceName, 
    Server, Average from Mytable FROM Mytable
)K
Pivot
(
    Max(Average) FOR Server IN (Server1, Server2, Server3, Server4, Server5)
) AS pvt