2016-11-09 5 views
2

죄송합니다 :이 게시물은 조금 긴 이것을 주위에 내 머리를 래핑하는 고투쿼리 (많이) XML 요소에서와 특정 텍스트에 대한 XML 데이터 (TSQL)는

(관련이 있었다 있는지 모든 것을 만들고 싶었다) 도착 작은. 나는 5 열

ID (varchar) 
Record value(XML) 
date (datetime) 
applicationtypeid (int) 
applicationstatusid(int) 

XML 내가 같은 외모에 관심이 데이터하지만 부분을 많이 포함하고있는 테이블이있다.

<GoodsAndServicesItemSummaryViewModelItems> 
    <GoodsAndServicesMasterViewModel> 
    <Id>1</Id> 
    <ClassId>1</ClassId> 
    <TermsText>text</TermsText> 
    <TermsCreationType>ManuallyEntered</TermsCreationType> 
    <Terms /> 

특히 "TermsCreationType"요소. 그 다음 3 문자열 중 하나가 될 수 있습니다에서 :

  • CopyFromPreapprovedTermsDatabase

고객이 파일 내용에 따라

  • CopyFromExistingMarks는 세 가지의 혼합물이있을 수 있고 할 수있을 ManuallyEntered 그들이 이론적으로 원했던만큼 많은 혼합물을 포함한다 : 예 :

    </PriorityClaimAdditionalDetailWizardStepViewModel> 
        <GoodsAndServicesMasterViewModel> 
        <Id>9</Id> 
        <ClassId>2</ClassId> 
        <TermsText>texty</TermsText> 
        <TermsCreationType>ManuallyEntered</TermsCreationType> 
        <Terms /> 
        </GoodsAndServicesMasterViewModel> 
        <GoodsAndServicesMasterViewModel> 
        <Id>10</Id> 
        <ClassId>1</ClassId> 
        <TermsText>text</TermsText> 
        <TermsCreationType>ManuallyEntered</TermsCreationType> 
        <Terms /> 
        </GoodsAndServicesMasterViewModel> 
    </GoodsAndServicesItemSummaryViewModelItems> 
    <GoodsAndServicesItemSummaryViewModelItemsUnMerged> 
        <GoodsAndServicesMasterViewModel> 
        <Id>9</Id> 
        <ClassId>9</ClassId> 
        <TermsText>test</TermsText> 
        <TermsCreationType>CopyFromExistingMarks</TermsCreationType> 
        <Terms /> 
        </GoodsAndServicesMasterViewModel> 
    

    는 그 유일한 값이 점에서의로

    1. 은 단지 그것을 한 번 또는 50 번을 표시할지 여부 (전술 중 하나 포함하는 특정 날짜 범위에서 얼마나 많은 레코드 수를 찾기 위해 노력하고있어 요소)

    2. 3 가지가 혼합 된 레코드.


    내 시도 지금까지 "단 하나 개의 요소"에 대해 이렇게이다 :

    SELECT Count (id) [pre-approved only] 
    FROM [TMWebForms].[dbo].[webformapplication] 
    WHERE trademarkid NOT IN (SELECT id 
              FROM [TMWebForms].[dbo].[webformapplication] 
              WHERE applicationtypeid = '5' 
                AND createddate BETWEEN '2016-08-01' AND '2016-08-31' 
                AND RECORDDATA.value('contains((//GoodsAndServicesWizardStepViewModel/GoodsAndServicesItemSummaryViewModelItems/GoodsAndServicesMasterViewModel/TermsCreationType/text())[1], "ManuallyEntered")', 'bit') = 1 
                AND applicationstatusid = 50 
                AND applicationtypeid = 5) 
         AND id NOT IN (SELECT id 
             FROM [TMWebForms].[dbo].[webformapplication] 
             WHERE applicationtypeid = '5' 
              AND createddate BETWEEN '2016-08-01' AND '2016-08-31' 
              AND RECORDDATA.value('contains((//GoodsAndServicesWizardStepViewModel/GoodsAndServicesItemSummaryViewModelItems/GoodsAndServicesMasterViewModel/TermsCreationType/text())[1], "CopyFromExistingMark")', 'bit') = 1 
              AND applicationstatusid = 50 
              AND applicationtypeid = 5) 
         AND createddate BETWEEN '2016-08-01' AND '2016-08-31' 
         AND RECORDDATA.value('contains((//GoodsAndServicesWizardStepViewModel/GoodsAndServicesItemSummaryViewModelItems/GoodsAndServicesMasterViewModel/TermsCreationType/text())[1], "CopyFromPreapprovedTermsDatabase")', 'bit') = 1 
         AND applicationstatusid = 50 
         AND applicationtypeid = 5 
    
    1. 이 긴 호흡하고 긴 슛을하지 최상의 성능 현명한! (나는 그것을 "좋아"를 사용하여 문자열로 변환하려고 생각했다. 그러나 그것은 나쁘지는 않을지라도 나쁜 것일 수도있다.)

    2. 내가 원한 것을 정확히 끌어 내지 못한다. 내게는 "CopyFromPreapprovedTermsDatabase"만 검색하지만 데이터를 조사 할 때 이것이 첫 번째 줄인 경우가 있지만 "수동 입력"이 있음을 알 수 있습니다.

    여기서 도움을 청하십시오!

  • +0

    @ Shnugo 안녕하세요, 불행히도 제가 원래 게시 한 것은 축소 된 예제였습니다. 필자는 원본 게시물을 편집하고 데이터베이스 레코드 (예 : 이전 섹션의 끝 요소를 포함하여 해당 레코드가 시작되는 방식을 볼 수 있음)에서 예제를 직접 복사하여 유효하도록했습니다. 닫기 요소 인 까지 이것은 정확히 DB에 쓰여진 방법입니다. 나가서 - 나는 순전히 카운트를 원해. 첫 번째 "1. & 2"에서 지정한 각각의 숫자가 몇 개인 지 알려주는 그림 이외의 것은 없습니다. 내 게시물의. 고맙습니다. – Nighthawkz

    +0

    죄송합니다. 충분히주의 깊게 보지 않았습니다 ... 게시 된 XML **이 유효하지 않습니다. 그러나 이것을 쉽게 복구하여 모형 *을 만들 수 있습니다 ... – Shnugo

    답변

    1

    하는 것처럼 시도이

    DECLARE @xml XML= 
    N'<SomeRoot> 
        <GoodsAndServicesItemSummaryViewModelItems> 
        <GoodsAndServicesMasterViewModel> 
         <Id>9</Id> 
         <ClassId>2</ClassId> 
         <TermsText>texty</TermsText> 
         <TermsCreationType>ManuallyEntered</TermsCreationType> 
         <Terms /> 
        </GoodsAndServicesMasterViewModel> 
        <GoodsAndServicesMasterViewModel> 
         <Id>10</Id> 
         <ClassId>1</ClassId> 
         <TermsText>text</TermsText> 
         <TermsCreationType>ManuallyEntered</TermsCreationType> 
         <Terms /> 
        </GoodsAndServicesMasterViewModel> 
        </GoodsAndServicesItemSummaryViewModelItems> 
        <GoodsAndServicesItemSummaryViewModelItemsUnMerged> 
        <GoodsAndServicesMasterViewModel> 
         <Id>9</Id> 
         <ClassId>9</ClassId> 
         <TermsText>test</TermsText> 
         <TermsCreationType>CopyFromExistingMarks</TermsCreationType> 
         <Terms /> 
        </GoodsAndServicesMasterViewModel> 
        </GoodsAndServicesItemSummaryViewModelItemsUnMerged> 
    </SomeRoot>'; 
    
    DECLARE @tbl TABLE(ID VARCHAR(10),Record_Value XML,[date] DATETIME,applicationtypeid INT,applicationstautsid INT); 
    INSERT INTO @tbl VALUES('SomeTest',@xml,GETDATE(),11,22); 
    

    --The CTE 모든 열을 선택되고 TermsCreationType의 실제 수를 추가 (I는 root를 추가하고 일부 개폐 태그를 추가했다) 주어진 text()

    WITH CTE AS 
    (
        SELECT * 
          ,Record_Value.value('count(//TermsCreationType[text()="ManuallyEntered"])','int') AS CountManuallyEntered 
          ,Record_Value.value('count(//TermsCreationType[text()="CopyFromExistingMarks"])','int') AS CountCopyFromExistingMarks 
          ,Record_Value.value('count(//TermsCreationType[text()="CopyFromPreapprovedTermsDatabase"])','int') AS CountCopyFromPreapprovedTermsDatabase 
        FROM @tbl 
    ) 
    

    와 --The 최종 SELECT는 분석하기 위해 큰 CASE WHEN 계층 구조를 사용 카운트

    SELECT * 
         ,CASE WHEN CTE.CountManuallyEntered=0 AND CTE.CountCopyFromExistingMarks=0 AND CTE.CountCopyFromPreapprovedTermsDatabase=0 THEN 'None' 
         ELSE 
          CASE WHEN CTE.CountManuallyEntered>0 AND CTE.CountCopyFromExistingMarks=0 AND CTE.CountCopyFromPreapprovedTermsDatabase=0 THEN 'Manually' 
          ELSE 
           CASE WHEN CTE.CountManuallyEntered=0 AND CTE.CountCopyFromExistingMarks>0 AND CTE.CountCopyFromPreapprovedTermsDatabase=0 THEN 'Existing' 
           ELSE 
            CASE WHEN CTE.CountManuallyEntered=0 AND CTE.CountCopyFromExistingMarks=0 AND CTE.CountCopyFromPreapprovedTermsDatabase>0 THEN 'Preapproved' 
            ELSE 
            'Mixed' 
            END 
           END 
          END 
         END AS CountAnalysis 
    FROM CTE; 
    
    +0

    감사합니다! 이것은 내가 필요한 것입니다. 직접 테이블에 쿼리 할 수있었습니다. 그리고 필요한 숫자를 정확하게 제공합니다. 또한 다른 xpath 구문에 대해서도 알려주었습니다. 나는 그것을 "포함하고"사용하여 모든 것을 시도했다. 카운트가 옵션 인지도 몰랐습니다! 이것은 미래에 매우 편리 할 것입니다. 다시 한 번 감사드립니다. – Nighthawkz