1

午後は Stack Overflow の善良な人々。

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

これらは、このクエリに基づく行の例です。

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

私が欲しいのはこれです:

DatabaseName    ObjectName      CounterName         InstanceName                Server1     Server2     Server3     Server4     Server5
DAG1DB01        logicaldisk     avg. disk sec/read  d:\mountpoints\DAG1DB01     13.616      17.508      12.775      13.148      10.091

どうすればこれを達成できるか知っている人はいますか?基本的に行を自分自身に適用しますか?

説明が必要な場合は、お気軽にお尋ねください。

ありがとう!

4

6 に答える 6

1

次のステートメントは、固定数の列(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フレーバーでサポートされています。

于 2012-07-03T15:53:51.713 に答える
1

アプローチ #1

デモを見るにはここをクリック

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)

アプローチ #2

デモを見るにはここをクリック

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
于 2012-07-03T16:00:47.383 に答える
1

PIVOTオペレーターは、このようなシナリオ向けに設計されています。これにより、探しているものが得られるはずです。

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
于 2012-07-03T15:45:26.440 に答える
0

次のように、サーバーごとに 1 回ずつ PERFMON テーブルに参加してみてください。

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

次に、結合ごとに 1 つの列を追加します。

AVG(Server1.Value) * 1000 AS [Server1]
于 2012-07-03T15:37:55.867 に答える
-1

こちらのリンクに示されている PIVOT テーブルの構文をご覧ください。

ピボット テーブルの例

これにより、あなたが求めていることを行うことができます。列ヘッダーを動的に生成するセクションを必ず確認してください。

于 2012-07-03T15:42:50.770 に答える
-3

テーブルを変更して余分な列を含め、更新を実行します Where server = 'Server2'

update d set server2 = 前のサーバー エントリの値 (たとえば、server = 'server2')

そのようにするのは面倒ですが、他の唯一のオプションは、SQL ステートメントを使用せずにテーブルを物理的に編集することです。

編集:私がお勧めするのは、2つのテーブルを作成することです。1つはすべての情報(データベース名など)を含み、もう1つはスコアを含みます

于 2012-07-03T15:32:25.220 に答える