2011-11-07 6 views
2

各従業員の売上ログを含むXMLファイルから別個の従業員のリストを収集する必要があります。残念ながら、XMLファイルのデータは正確に「一貫性」ではありません。ファイルには、そのように構成されていますSQL Serverの反復データから別個のリストを設定する

<Sale EmployeeId="67890" EmployeeName="John" EmployeeManagerId="12345" 
     CustomerName="Bob" SaleNumber="..." /> 
<Sale EmployeeId="67890" EmployeeName="John" EmployeeManagerId="12345" 
     CustomerName="Pat" SaleNumber="..." /> 
<Sale EmployeeId="67890" EmployeeName=""  EmployeeManagerId="12345" 
     CustomerName="Sally" SaleNumber="..." /> 
<Sale EmployeeId="67890" EmployeeName=""  EmployeeManagerId="12345" 
     CustomerName="Sue" SaleNumber="..." /> 
<Sale EmployeeId="67890" EmployeeName="John" EmployeeManagerId=""  
     CustomerName="Jack" SaleNumber="..." /> 
<Sale EmployeeId="58203" EmployeeName="Fred" EmployeeManagerId=""  
     CustomerName="Bill" SaleNumber="..." /> 

このXMLファイルは、処理のために、SQL Serverのストアドプロシージャに(XMLなど)、その内容を渡すWebアプリケーションにアップロードされます。このファイルのサイズ(最大30,000要素)のため、私は可能な限りWebアプリケーションでほとんど処理をしません。

私がこれまで考えてきた最良の解決策は、それぞれ異なるEmployeeIdおよびManagerId値に対して1つの行を持つ一時テーブルを作成することです。次に、テーブル内の各行について、一致するEmployeeIdを持つXML要素をループします。名前がnullでないエントリが見つかるまで(ManagerIdに対して繰り返します)。

したがって、一意の従業員IDごとに、結果を2回繰り返して名前とマネージャーのIDが見つかるかどうかを確認します。

ファイルが処理されると、私はこのように見えるように、Employeeテーブルを期待する:

+---------+------+------------+ 
| Id (PK) | Name | ManagerId | 
+---------+------+------------+ 
| 12345 | NULL | NULL  | 
| 67890 | John | 12345  | 
| 58203 | Fred | NULL  | 
+---------+------+------------+ 

は、このためのより効率的な(そしてあまり手続き)解決策はありますか?

+0

あなたの最終目標は何ですか?このデータをSQLデータベースにプッシュしますか? XMLを処理するためにどのような言語を使用していますか? – arb

+0

最後に、ファイル内のEmployeeIdとManagerIdは、SQLデータベース内のEmployeeテーブルにエントリを持つ必要があります。私は、可能であれば、従業員(氏名またはマネージャーID)に関する多くの情報が不足している場合も記入したいと思いますが、提供されている情報に頼ることはできません。 –

+0

私は、XML処理がSQL Serverのストアドプロシージャで実行されていることを指定する質問を更新しました。そのため、使用されている言語はT-SQLです。 –

答えて

2
declare @xml xml = ' 
<Sale EmployeeId="67890" EmployeeName="John" EmployeeManagerId="12345" 
     CustomerName="Bob" SaleNumber="..." /> 
<Sale EmployeeId="67890" EmployeeName="John" EmployeeManagerId="12345" 
     CustomerName="Pat" SaleNumber="..." /> 
<Sale EmployeeId="67890" EmployeeName=""  EmployeeManagerId="12345" 
     CustomerName="Sally" SaleNumber="..." /> 
<Sale EmployeeId="67890" EmployeeName=""  EmployeeManagerId="12345" 
     CustomerName="Sue" SaleNumber="..." /> 
<Sale EmployeeId="67890" EmployeeName="John" EmployeeManagerId=""  
     CustomerName="Jack" SaleNumber="..." /> 
<Sale EmployeeId="58203" EmployeeName="Fred" EmployeeManagerId=""  
     CustomerName="Bill" SaleNumber="..." />' 

-- "E1 is all employees" 
;with E1 as  
(
    select T.N.value('@EmployeeId', 'int') as Id, 
     T.N.value('@EmployeeName', 'nvarchar(100)') as Name, 
     T.N.value('@EmployeeManagerId', 'int') as ManagerID 
    from @xml.nodes('/Sale') as T(N) 
), 
-- E2 groups on id to get only one emp for each id 
E2 as 
(
    select Id, max(Name) as Name, nullif(max(ManagerID), 0) as ManagerID 
    from E1 
    group by Id 
), 
-- "All manager id's" 
M as 
(
    select distinct T.N.value('@EmployeeManagerId', 'int') as Id 
    from @xml.nodes('/Sale') as T(N) 
    where T.N.value('@EmployeeManagerId', 'int') <> 0  
) 
-- "All unique employees" 
select Id, Name, ManagerID 
from E2 
union all 
-- "Add managers with a lookup against emp for name and manager id" 
select M.Id, E2.Name, E2.ManagerID 
from M 
    left outer join E2 
    on M.Id = E2.ID 
3

これにより結果が得られますが、サンプルデータが異なる場合はクリーンアップ作業が必要になることがあります。

DECLARE @T TABLE (x XML) 
INSERT INTO @T 
     (x) 
VALUES ('<Sale EmployeeId="67890" EmployeeName="John" EmployeeManagerId="12345"  CustomerName="Bob" SaleNumber="..." />') 
    , ('<Sale EmployeeId="67890" EmployeeName="John" EmployeeManagerId="12345"  CustomerName="Pat" SaleNumber="..." />'), 
     ('<Sale EmployeeId="67890" EmployeeName=""  EmployeeManagerId="12345"  CustomerName="Sally" SaleNumber="..." />') 
    , ('<Sale EmployeeId="67890" EmployeeName=""  EmployeeManagerId="12345"  CustomerName="Sue" SaleNumber="..." />'), 
     ('<Sale EmployeeId="67890" EmployeeName="John" EmployeeManagerId=""    CustomerName="Jack" SaleNumber="..." />'), 
     ('<Sale EmployeeId="58203" EmployeeName="Fred" EmployeeManagerId=""    CustomerName="Bill" SaleNumber="..." />') 

;WITH c 
AS (

SELECT DISTINCT ID = x.value('(/Sale/@EmployeeId)[1]', 'int') 
     , NAME = x.value('(/Sale/@EmployeeName)[1]', 'varchar(4)') 
     , ManagerID = x.value('(/Sale/@EmployeeManagerId)[1]', 'int') 
FROM @t 
WHERE x.value('(/Sale/@EmployeeName)[1]', 'varchar(4)') <> '' 
) 

SELECT ID, NAME, ManagerID =MIN(NULLIF(ManagerID, 0)) 
FROM c 
GROUP BY ID, Name 
UNION 
SELECT ManagerID, NULL, NULL 
FROM c 
WHERE ManagerID NOT IN (SELECT DISTINCT ID FROM c) 
    AND ManagerID <> 0 
関連する問題