2016-09-28 7 views
2

SQL Serverには、各テーブルの特定の計算条件を考慮する必要があるテーブルグループがあります。この問題はユーザーごとにグループ化する必要があります。 1つのテーブルに含まれ、関係テーブルを介してカウントする必要があるテーブルにマップされます。COUNT複数のテーブルとリレーションシップとユーザー

これは、これはIR表で関係テーブル

Relationship User Work Item 
Analyst   1  IR1 
Analyst   2  IR2 
Analyst   2  IR3 
Analyst   1  IR4 
User   3  IR1 
Analyst   1  SR2 
Analyst   1  SR3 
Analyst   2  SR4 

である(SRテーブルが同一である)

ID  Status 
IR1 Active 
IR2 Active 
IR3 Closed 
IR4 Active 

これは私が必要なもの、ユーザーテーブル

User  Name 
1  Dave 
2  Jim 
3  Karl 

です以下のようなアクティブなアイテムのみをカウントするテーブルです

Name IR Count SR Count 
Dave 2   2 
Jim 1   1 

私は現在、ステータスに関係なくすべてのユーザーをカウントすることができるように思われるが、これは左の結合のためかもしれないと思う。私は基本的には:

Select u.name, 
count (ir), 
count (sr) from user u 
Inner join relationship r on r.user=u.user and r.relationship = 'Analyst' 
Left Join IR on r.workitem=ir.id and ir.Status = 'Active' 
Left Join SR on r.workitem=sr.id and sr.Status = 'Active' 
Group by u.name 

私は可能な限り上記を単純化しました。これは実際のクエリです:

SELECT 
u.DisplayName as Analyst, 
u.BaseManagedEntityId as AUsername, 
COUNT(distinct i.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) AS 'Active Incidents', 
COUNT(distinct sr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Service Requests', 
COUNT(distinct cr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Change Requests', 
COUNT(distinct ma.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Manual Activities' 
FROM MTV_System$Domain$User u 
INNER JOIN RelationshipView r ON r.TargetEntityId = u.BaseManagedEntityId AND r.RelationshipTypeId = '15E577A3-6BF9-6713-4EAC-BA5A5B7C4722' AND r.IsDeleted ='0' 
LEFT JOIN MTV_System$WorkItem$Incident i ON r.SourceEntityId = i.BaseManagedEntityId AND (i.Status_785407A9_729D_3A74_A383_575DB0CD50ED != '2B8830B6-59F0-F574-9C2A-F4B4682F1681' AND i.Status_785407A9_729D_3A74_A383_575DB0CD50ED != 'BD0AE7C4-3315-2EB3-7933-82DFC482DBAF') 
LEFT JOIN MTV_System$WorkItem$ServiceRequest sr ON r.SourceEntityId = SR.BaseManagedEntityId AND (sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F = '72B55E17-1C7D-B34C-53AE-F61F8732E425' OR sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F = '59393F48-D85F-FA6D-2EBE-DCFF395D7ED1' OR sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F = '05306BF5-A6B9-B5AD-326B-BA4E9724BF37') 
LEFT JOIN MTV_System$WorkItem$ChangeRequest cr on r.SourceEntityId = cr.BaseManagedEntityId AND (cr.Status_72C1BC70_443C_C96F_A624_A94F1C857138 = '6D6C64DD-07AC-AAF5-F812-6A7CCEB5154D' or cr.Status_72C1BC70_443C_C96F_A624_A94F1C857138 = 'DD6B0870-BCEA-1520-993D-9F1337E39D4D') 
LEFT JOIN MTV_System$WorkItem$Activity$ManualActivity MA on r.SourceEntityId = ma.BaseManagedEntityId AND (ma.Status_8895EC8D_2CBF_0D9D_E8EC_524DEFA00014 = '11FC3CEF-15E5-BCA4-DEE0-9C1155EC8D83' OR ma.Status_8895EC8D_2CBF_0D9D_E8EC_524DEFA00014 = 'D544258F-24DA-1CF3-C230-B057AAA66BED') 

GROUP BY u.DisplayName,u.BaseManagedEntityId 
Order by u.DisplayName 
+0

どのような問題があるようですか?あなたの例で列名をクリーンアップし、あなたのカウントにDISTINCTを追加すると、望みの結果が得られます。より複雑なクエリが使用している方法はどれですか。どのような行動/カウントの問題を具体的に修正しようとしていますか? – Matt

+0

カウント数に違いがありませんでした。アナリストの関係を持つユーザーを、フィルター条件を満たすアクティブな項目がない結果表に戻していました。ユーザーが関係を持っていても作業項目がアクティブでない場合は、返されません。 – Alex

+0

これはLEFT JOINsのためです。 whereステートメントのテストで制約を受けて、左の結合の値の少なくとも1つがnullでないことを確認したら、それは起こりません。しかし、たとえIRとSRが0でなく、単にそれらを内部結合にしたいだけなら、例えばIR count = 0とSR Count> 0を持つことは可能です – Matt

答えて

1

をオフに基づいて動作するようです、あなた以上の簡素化は、あなたのあなたの一部から、あなたの問題と思われるものを失っているようですコメント。左ジョインを使用すると、他のテーブルの1つのカウントがない場合でも、任意のユーザーが含まれます。ただし、結果セットに少なくとも1つのインシデントおよび/または1つのリクエストおよび/または1つの変更要求を持つユーザーのみを含める場合は、あなたが事件+要求+ ... = 0を取り除くために事実の後にやっているアグリゲーションをフィルタリングすることもできますし、WHEN以外のテーブルがすべてNULLでないというWHEREステートメントを追加することによってそれらをフィルタリングすることもできます。 OR IS NOT NULLと同じです...

SELECT 
u.DisplayName as Analyst, 
u.BaseManagedEntityId as AUsername, 
COUNT(distinct i.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) AS 'Active Incidents', 
COUNT(distinct sr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Service Requests', 
COUNT(distinct cr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Change Requests', 
COUNT(distinct ma.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Manual Activities' 
FROM 
    MTV_System$Domain$User u 
    INNER JOIN RelationshipView r 
    ON r.TargetEntityId = u.BaseManagedEntityId 
    AND r.RelationshipTypeId = '15E577A3-6BF9-6713-4EAC-BA5A5B7C4722' 
    AND r.IsDeleted ='0' 
    LEFT JOIN MTV_System$WorkItem$Incident i 
    ON r.SourceEntityId = i.BaseManagedEntityId 
    AND i.Status_785407A9_729D_3A74_A383_575DB0CD50ED NOT IN ('2B8830B6-59F0-F574-9C2A-F4B4682F1681','BD0AE7C4-3315-2EB3-7933-82DFC482DBAF') 
    LEFT JOIN MTV_System$WorkItem$ServiceRequest sr 
    ON r.SourceEntityId = SR.BaseManagedEntityId 
    AND sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F IN ('72B55E17-1C7D-B34C-53AE-F61F8732E425','59393F48-D85F-FA6D-2EBE-DCFF395D7ED1','05306BF5-A6B9-B5AD-326B-BA4E9724BF37') 
    LEFT JOIN MTV_System$WorkItem$ChangeRequest cr 
    ON r.SourceEntityId = cr.BaseManagedEntityId 
    AND cr.Status_72C1BC70_443C_C96F_A624_A94F1C857138 IN ('6D6C64DD-07AC-AAF5-F812-6A7CCEB5154D','DD6B0870-BCEA-1520-993D-9F1337E39D4D') 
    LEFT JOIN MTV_System$WorkItem$Activity$ManualActivity MA 
    ON r.SourceEntityId = ma.BaseManagedEntityId 
    AND ma.Status_8895EC8D_2CBF_0D9D_E8EC_524DEFA00014 IN ('11FC3CEF-15E5-BCA4-DEE0-9C1155EC8D83','D544258F-24DA-1CF3-C230-B057AAA66BED') 
WHERE 
    i.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C IS NOT NULL 
    OR sr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C IS NOT NULL 
    OR cr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C IS NOT NULL 
    OR ma.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C IS NOT NULL 
GROUP BY u.DisplayName,u.BaseManagedEntityId 
Order by u.DisplayName 

また、ORの代わりに結合条件でINとNOT INのユーザーに注意してください。

+0

IN/NOT INの助けを借りてくれてありがとうございました。あなたはまた、簡素化されています。あなたの助けをたくさんありがとう – Alex

+0

@Alex喜んでそれはあなたのために働く、人々があなたの質問を理解し、評判のポイントが授与されているように私の答えを受け入れることを検討してください。ありがとう。 http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – Matt

0

問題がcount()です。代わりに、あなたはcount(distinct)をしたい:

Select u.name, 
     count(distinct ir), 
     count(distinct sr) 
from user u 
. . . 

これはirsr値の間のデカルト積を生成します。各グループに大きな数字がある場合は、joinの前に集約する方が良い方法です。

+0

Hmmmどちらもうまくいきません。ステータスがアクティブでないカウント内のユーザ – Alex

+0

ジョインではなくジョインの後でフィルタをどこに置く必要があるだけです。 – Alex

+0

@Alexアライメントの右側である表に条件を設定すると、@Alex LEFT JOIN where句では、あなたが望むものでないINNER JOINになります。 – Matt

0

以下のスクリプトを試してみてください。

SELECT u.name 
    ,SUM(t1.[IR Count]) [IR Count] 
    ,SUM(t2.[SR Count]) [SR Count] 
FROM #user u 
INNER JOIN #relationship r on r.[user]=u.[user]and r.relationship = 'Analyst' 
    CROSS APPLY (SELECT COUNT(DISTINCT ID) [IR Count] 
       FROM #IR ir WHERE r.workitem=ir.id and ir.Status = 'Active') t1 
    CROSS APPLY (SELECT COUNT(DISTINCT ID) [SR Count] 
       FROM #SR sr WHERE r.workitem=sr.id and sr.Status = 'Active')t2 
GROUP BY u.name 

OUTPUT:SRテーブルはIR表のと同じであれば、あなたのサンプル出力で

enter image description here

SR Countは、間違っている(SR3の状況は、ユーザーのため閉鎖され'dave'なので無視されます)。

0
;WITH T AS 
(
    SELECT 
     U.UserID, 
     U.Name, 
     CASE WHEN R.WorkItem LIKE 'IR%' THEN R.WorkItem ELSE '' END AS IRCode, 
     CASE WHEN R.WorkItem LIKE 'SR%' THEN R.WorkItem ELSE '' END AS SRCode 
    FROM @tblUser U 
    INNER JOIN @tblRelationship R ON U.UserId=R.UserId 
) 
SELECT 
    Name, 
    SUM(CASE IRCode WHEN '' THEN 0 ELSE 1 END) AS 'IR Count', 
    SUM(CASE SRCode WHEN '' THEN 0 ELSE 1 END) AS 'SR Count' 
FROM T 
WHERE 
(
    (T.IRCode='' 
    OR 
    T.SRCode='') 
    AND 
    (
     T.IRCode IN (SELECT ID FROM @tblIR WHERE Status='Active') 
     OR 
     T.SRCode IN (SELECT ID FROM @tblSR WHERE Status='Active') 
    ) 
) 
GROUP BY T.Name 
0

これは私がそれを作ってみたものです実際のテーブル

SELECT 
u.DisplayName as Analyst, 
u.BaseManagedEntityId as AUsername, 
COUNT(distinct i.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) AS 'Active Incidents', 
COUNT(distinct sr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Service Requests', 
COUNT(distinct cr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Change Requests', 
COUNT(distinct ma.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Manual Activities' 
FROM MTV_System$Domain$User u 
    LEFT JOIN RelationshipView r ON r.TargetEntityId = u.BaseManagedEntityId AND r.RelationshipTypeId = '15E577A3-6BF9-6713-4EAC-BA5A5B7C4722' AND r.IsDeleted ='0' 
    LEFT JOIN MTV_System$WorkItem$Incident i ON r.SourceEntityId = i.BaseManagedEntityId 
    LEFT JOIN MTV_System$WorkItem$ServiceRequest sr ON r.SourceEntityId = SR.BaseManagedEntityId 
    LEFT JOIN MTV_System$WorkItem$ChangeRequest cr on r.SourceEntityId = cr.BaseManagedEntityId 
LEFT JOIN MTV_System$WorkItem$Activity$ManualActivity MA on r.SourceEntityId = ma.BaseManagedEntityId 
Where (i.Status_785407A9_729D_3A74_A383_575DB0CD50ED != '2B8830B6-59F0-F574-9C2A-F4B4682F1681' AND i.Status_785407A9_729D_3A74_A383_575DB0CD50ED != 'BD0AE7C4-3315-2EB3-7933-82DFC482DBAF') 
OR (sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F = '72B55E17-1C7D-B34C-53AE-F61F8732E425' OR sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F = '59393F48-D85F-FA6D-2EBE-DCFF395D7ED1' OR sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F = '05306BF5-A6B9-B5AD-326B-BA4E9724BF37') 
OR (cr.Status_72C1BC70_443C_C96F_A624_A94F1C857138 = '6D6C64DD-07AC-AAF5-F812-6A7CCEB5154D' or cr.Status_72C1BC70_443C_C96F_A624_A94F1C857138 = 'DD6B0870-BCEA-1520-993D-9F1337E39D4D') 
OR (ma.Status_8895EC8D_2CBF_0D9D_E8EC_524DEFA00014 = '11FC3CEF-15E5-BCA4-DEE0-9C1155EC8D83' OR ma.Status_8895EC8D_2CBF_0D9D_E8EC_524DEFA00014 = 'D544258F-24DA-1CF3-C230-B057AAA66BED') 
GROUP BY u.DisplayName,u.BaseManagedEntityId 
Order by u.DisplayName 
+0

hmmmこれは、いくつかのテーブルを内部結合にし、他のものは依然としてLEFT結合であり、それらのステータスカラムのいずれかにNULLを含めることができる場合、さらに大きな問題が発生します。 – Matt

+0

ステータスカラムにはNULL値を含めることはできません。 – Alex

+0

それは良い。しかし、もしi.Statusがあなたが望んでいないものの1つであるが、同じレコードがsr.statusesのものと一致するなら、あなたは間違った状態のカウントを得るでしょう。条件は結合にとどまるべきです。あなたができることの1つは、集計を取り除き、それがどのようなものか、集約する前に望むものかを見るためにレコードセットを調べることです。この場合、私はそれがあるとは思わない。 – Matt

関連する問題