web-dev-qa-db-fra.com

Sélectionner avec l'instruction CASE SQL Server 2008 R2

J'ai une requête qui utilise une instruction CASE pour évaluer les comptes. La requête recherche les valeurs sous forme vectorielle. Ainsi, par exemple, si je suis un patient, je peux avoir plusieurs codes de diagnostic, mais ils ne sont pas stockés sous forme de valeurs de colonne, ils sont stockés dans une autre ligne, comme suit:

VISIT_ID | CLASFCD
123      | 196.0
123      | 197.0
123      | 198.0
321      | 199.0
321      | 650.9
222      | 111
555      | ...
...

Ma requête utilise une déclaration de cas comme suit:

, CASE
    WHEN DV.ClasfCd IN (
    '196.0','196.1','196.2','196.3','196.5','196.6','196.8','196.9',
    '197.0','197.1','197.2','197.3','197.4','197.5','197.6','197.7',
    '197.8','198.2','198.3','198.4','198.5','199.1','209.7'
    )
    THEN 6
    ELSE 0
  END AS PRIN_DX_CD_5

Je le fais pour 5 groupes de codes différents. En réalité, si les critères sont remplis pour l'un de ces groupes, les résultats sont renvoyés sur une autre ligne plutôt que sur la même ligne. Voici un exemple des données que je récupère:

VISIT_ID | CC GROUP 1 | CC GROUP 2 | CC GROUP 3 | CC GROUP 4 | CC GROUP 5 | TOTAL
123      | 1          | 0          | 0          | 0          | 0          | 1
123      | 0          | 2          | 0          | 0          | 0          | 2
123      | 0          | 0          | 0          | 0          | 0          | 0

Ce que je veux retourner est le suivant:

VISIT_ID | CC GROUP 1 | CC GROUP 2 | CC GROUP 3 | CC GROUP 4 | CC GROUP 5 | TOTAL
123      | 1          | 2          | 0          | 0          | 0          | 3
321      | 1          | 0          | 0          | 0          | 6          | 6

Le score total final ne peut pas dépasser 6.

Toute la requête, dans une certaine brièveté, est ici, elle fait partie d'une requête en plusieurs parties, j'apporte des modifications à l'original:

SET ANSI_NULLS OFF
GO
DECLARE @SD DATETIME
DECLARE @ED DATETIME
SET @SD = '2013-01-01';
SET @ED = '2013-05-31';

-- @CM TABLE DECLARATION #############################################]
DECLARE @CM TABLE (
ENCOUNTER_ID VARCHAR(200)
, [MRN CM] VARCHAR(200)
, NAME VARCHAR(500)
, [CC GRP ONE SCORE] VARCHAR(20)
, [CC GRP TWO SCORE] VARCHAR(20)
, [CC GRP THREE SCORE] VARCHAR(20)
, [CC GRP FOUR SCORE] VARCHAR(20)
, [CC GRP FIVE SCORE] VARCHAR(20)
, [CC LACE SCORE] INT
)
--####################################################################]

INSERT INTO @CM
SELECT
C.PT_NO
, C.MED_REC_NO
, C.PT_NAME
, C.PRIN_DX_CD_1
, C.PRIN_DX_CD_2
, C.PRIN_DX_CD_3
, C.PRIN_DX_CD_4
, C.PRIN_DX_CD_5
, CASE
    WHEN (C.PRIN_DX_CD_1+C.PRIN_DX_CD_2+C.PRIN_DX_CD_3+C.PRIN_DX_CD_4+C.PRIN_DX_CD_5) = 0 THEN 0
    WHEN (C.PRIN_DX_CD_1+C.PRIN_DX_CD_2+C.PRIN_DX_CD_3+C.PRIN_DX_CD_4+C.PRIN_DX_CD_5) = 1 THEN 1
    WHEN (C.PRIN_DX_CD_1+C.PRIN_DX_CD_2+C.PRIN_DX_CD_3+C.PRIN_DX_CD_4+C.PRIN_DX_CD_5) = 2 THEN 2
    WHEN (C.PRIN_DX_CD_1+C.PRIN_DX_CD_2+C.PRIN_DX_CD_3+C.PRIN_DX_CD_4+C.PRIN_DX_CD_5) = 3 THEN 3
    WHEN (C.PRIN_DX_CD_1+C.PRIN_DX_CD_2+C.PRIN_DX_CD_3+C.PRIN_DX_CD_4+C.PRIN_DX_CD_5) = 4 THEN 4
    WHEN (C.PRIN_DX_CD_1+C.PRIN_DX_CD_2+C.PRIN_DX_CD_3+C.PRIN_DX_CD_4+C.PRIN_DX_CD_5) = 5 THEN 5
    WHEN (C.PRIN_DX_CD_1+C.PRIN_DX_CD_2+C.PRIN_DX_CD_3+C.PRIN_DX_CD_4+C.PRIN_DX_CD_5) >= 6 THEN 6
  END AS CC_LACE_SCORE

FROM (
    SELECT DISTINCT PAV.PT_NO
    , MED_REC_NO
    , PT_NAME
    , CASE
        WHEN dv.ClasfCd IN (

        )
        THEN 1
        ELSE 0
      END AS PRIN_DX_CD_1
    , CASE
        WHEN DV.ClasfCd IN (

        )
        THEN 2
        ELSE 0
    END AS PRIN_DX_CD_2
    , CASE
        WHEN DV.ClasfCd IN (

        )
        THEN 3
        ELSE 0
      END AS PRIN_DX_CD_3
    , CASE
        WHEN DV.ClasfCd IN (

        )
        THEN 4
        ELSE 0
      END AS PRIN_DX_CD_4
    , CASE
        WHEN DV.ClasfCd IN (

        )
        THEN 6
        ELSE 0
      END AS PRIN_DX_CD_5

      FROM smsdss.BMH_PLM_PtAcct_V PAV
      JOIN smsdss.BMH_PLM_PtAcct_Clasf_Dx_V DV
      ON PAV.PtNo_Num = DV.PtNo_Num

      WHERE Dsch_Date BETWEEN @SD AND @ED


)C

GROUP BY C.PT_NO
, C.MED_REC_NO
, C.PT_NAME
, C.PRIN_DX_CD_1
, C.PRIN_DX_CD_2
, C.PRIN_DX_CD_3
, C.PRIN_DX_CD_4
, C.PRIN_DX_CD_5
ORDER BY C.Pt_No

SELECT * FROM @CM

merci de votre aide,

3
MCP_infiltrator

Le problème est que vous incluez les colonnes calculées PRIN_DX_ dans l'agrégation. Au lieu de cela, supprimez-les de l'agrégation et choisissez simplement la valeur non-0 (à l'aide de max()):

SELECT C.PT_NO, C.MED_REC_NO, C.PT_NAME,
       max(C.PRIN_DX_CD_1) as PRIN_DX_CD_1,
       max(C.PRIN_DX_CD_2) as PRIN_DX_CD_2,
       max(C.PRIN_DX_CD_3) as PRIN_DX_CD_3,
       max(C.PRIN_DX_CD_4) as PRIN_DX_CD_4,
       max(C.PRIN_DX_CD_5) as PRIN_DX_CD_5,
       (case when max(C.PRIN_DX_CD_1) + max(C.PRIN_DX_CD_2) + max(C.PRIN_DX_CD_3) + 
                  max(C.PRIN_DX_CD_4) + max(C.PRIN_DX_CD_5) < 6
             then max(C.PRIN_DX_CD_1) + max(C.PRIN_DX_CD_2) + max(C.PRIN_DX_CD_3) + 
                  max(C.PRIN_DX_CD_4) + max(C.PRIN_DX_CD_5)
             else 6
        end) as CC_LACE_SCORE
FROM (SELECT DISTINCT PAV.PT_NO, MED_REC_NO, PT_NAME,
             (CASE WHEN dv.ClasfCd IN ()
                   THEN 1
                   ELSE 0
              END) AS PRIN_DX_CD_1,
             (CASE WHEN DV.ClasfCd IN ()
                   THEN 2
                   ELSE 0
              END) AS PRIN_DX_CD_2
             (CASE WHEN DV.ClasfCd IN ()
                   THEN 3
                   ELSE 0
              END) AS PRIN_DX_CD_3,
             (CASE WHEN DV.ClasfCd IN ()
                   THEN 4
                   ELSE 0
              END) AS PRIN_DX_CD_4,
             (CASE WHEN DV.ClasfCd IN ()
                   THEN 6
                   ELSE 0
              END) AS PRIN_DX_CD_5   
      FROM smsdss.BMH_PLM_PtAcct_V PAV join
           smsdss.BMH_PLM_PtAcct_Clasf_Dx_V DV
           ON PAV.PtNo_Num = DV.PtNo_Num
      WHERE Dsch_Date BETWEEN @SD AND @ED
     ) C
GROUP BY C.PT_NO, C.MED_REC_NO, C.PT_NAME
ORDER BY C.Pt_No;

Je suppose que la variable distinct de la sous-requête n'est peut-être pas nécessaire, mais cela dépend de l'apparence réelle de vos données.

7
Gordon Linoff

METTRE À JOUR:

Vous devez absolument vous pencher sur le pivot, comme le dit @Darren Kopp

Créer un tableau pour mapper vos valeurs dans les clauses IN avec des groupes

Puis faire pivoter

Puis simpifiez votre cas quand minimum(val, 6) en utilisant quelque chose comme

CREATE FUNCTION Minimum
(@Param1 Integer, @Param2 Integer)
Returns Table As
Return(Select Case When @Param1 < @Param2 
               Then @Param1 Else @Param2 End MinValue)

Donc, votre table cdmap serait

6    |    '196.0'
6    |    '196.1'
6    |    '196.2'


SELECT ....,  [1], [2], [4], [6]
FROM
(
FROM smsdss.BMH_PLM_PtAcct_V PAV
  JOIN smsdss.BMH_PLM_PtAcct_Clasf_Dx_V DV
  ON PAV.PtNo_Num = DV.PtNo_Num
  JOIN cdmap c on c.ClasfCd = dv.ClasfCd
  WHERE Dsch_Date BETWEEN @SD AND @ED
 ) AS SourceTable
 PIVOT
 (
  ...
  FOR c.ClasfCd IN ([1], [2], [4], [6])
 ) AS PivotTable;
1
vittore