【问题标题】:Partitioning/Grouping/listing over data that have already been partitioned with ROW_NUMBER对已使用 ROW_NUMBER 分区的数据进行分区/分组/列出
【发布时间】:2022-07-29 01:33:45
【问题描述】:

我制作了一个 TSQL 脚本,它几乎可以从数据库(多个表)中获取/过滤数据集,并将其转储到不同数据库上的其他表中。到目前为止一切顺利。

脚本如下所示:

DECLARE @FechaInicio DATETIME = '2022-01-26 00:00:00.000';
DECLARE @FechaFin DATETIME = '2022-02-25 23:59:00.000'

WHILE (@FechaInicio <= @FechaFin)
BEGIN
    PRINT '
    ;WITH CTE_CORTES AS (
        SELECT
            XX.PACIENTE_nVECES_REPETIDOS,
            XX.FECHA_DEL_ESTUDIO,
            XX.UNIDAD_TRATANTE,
            XX.ApellidoPaterno,
            XX.ApellidoMaterno,
            XX.NOMBRE_DEL_PACIENTE,
            XX.NSS,
            XX.CLAVE_CPIM,
            XX.AGREGADO_MEDICO,
            XX.TIPO_DE_ESTUDIO,
            XX.MODALIDAD,
            XX.INTERPRETACION,
            XX.PARTICION_UID
        FROM
        (
            SELECT
                *,
                ROW_NUMBER() OVER (PARTITION BY WW.UIDESTUDIO ORDER BY WW.FECHA_DEL_ESTUDIO) AS PARTICION_UID
            FROM
                (
                    SELECT
                        ROW_NUMBER() OVER(PARTITION BY (SUBSTRING(R.NSS,1,10)) ORDER BY R.FECHA_DEL_ESTUDIO) AS PACIENTE_nVECES_REPETIDOS,
                        R.UIDESTUDIO,
                        R.FECHA_DEL_ESTUDIO,
                        R.UNIDAD_TRATANTE,
                        R.ApellidoPaterno,
                        R.ApellidoMaterno,
                        R.NOMBRE_DEL_PACIENTE,
                        R.NSS,
                        R.CLAVE_CPIM,
                        R.AGREGADO_MEDICO,
                        R.TIPO_DE_ESTUDIO,
                        R.MODALIDAD,
                        CASE
                            WHEN R.RESULTADO IS NULL
                                THEN ''SIN INTERPRETACION''
                            ELSE CONVERT(VARCHAR, R.RESULTADO, 103)
                        END AS INTERPRETACION
                    FROM
                        (
                            SELECT
                                COUNT(T.UIDESTUDIO) AS VECES_REPETIDO,
                                *
                            FROM
                            (
                                SELECT
                                    --ROW_NUMBER() OVER(ORDER BY FECHAESTUDIO) AS CONSECUTIVO,
                                    E.IdPaciente,
                                    E.FOLIO AS UIDESTUDIO,
                                    CAST (E.FechaEstudio AS smalldatetime) AS FECHA_DEL_ESTUDIO,
                                    ''HGZ 98'' AS UNIDAD_TRATANTE,
                                    P.ApellidoPaterno,
                                    P.ApellidoMaterno,
                                    CONCAT(P.PrimerNombre,'' '' /*COLLATE Modern_Spanish_CI_AI*/, P.SegundoNombre) AS NOMBRE_DEL_PACIENTE,
                                    NSS = left(P.Folio + replicate(''0'', 10), 10),
                                    CASE    
                                        WHEN E.Modalidades=''CR''
                                            THEN ''80.15.001''      
                                        WHEN E.Modalidades=''DX''
                                            THEN ''80.15.001''
                                        WHEN E.Modalidades=''MG''
                                            THEN ''80.15.002''
                                        WHEN E.Modalidades=''BDUS'' OR E.Modalidades=''BMD''
                                            THEN ''80.15.003''
                                        WHEN E.Modalidades=''RF''
                                            THEN ''80.15.004''
                                        WHEN E.Modalidades= ''US''
                                            THEN    (
                                                        CASE 
                                                            WHEN E.Descripcion NOT LIKE ''%DOPPLER%'' /*OR E.Descripcion NOT LIKE ''%DOPLER%''*/ THEN ''80.15.005''
                                                            WHEN E.Descripcion  LIKE ''%DOPPLER%'' OR E.Descripcion LIKE ''%DOPLER%'' THEN ''80.15.006''
                                                        ELSE ''80.15.005''
                                            END     )
                                        WHEN E.Modalidades= ''CT''
                                            THEN    (
                                                        CASE    
                                                            WHEN E.Descripcion NOT LIKE ''%CONTRAST%'' THEN ''80.15.007''
                                                            WHEN E.Descripcion LIKE ''%CONTRASTADO%'' /*OR E.Descripcion LIKE ''%GADOLIN%''*/ THEN ''80.15.008''
                                                        ELSE ''80.15.007''
                                            END     )
                                        WHEN E.Modalidades=''MR''
                                            THEN    (
                                                        CASE    
                                                            WHEN E.Descripcion NOT LIKE ''%CONTRASTADO%'' OR E.Descripcion NOT LIKE ''%GADOLIN%'' THEN ''80.15.009''
                                                            WHEN E.Descripcion  LIKE ''%CONTRAST%'' OR E.Descripcion LIKE ''%GADOLIN%'' THEN ''80.15.010''
                                                        ELSE ''80.15.009''
                                            END     )
                                        WHEN E.Modalidades=''XA''
                                            THEN ''80.15.011''
                                        WHEN E.Modalidades = ''ES''
                                            THEN ''80.15.012''
                                        ELSE ''80.15.014''
                                    END AS CLAVE_CPIM,
                                    AGREGADO_MEDICO = LEFT(SUBSTRING(P.Folio,11,18) + REPLICATE(''0'',8),8),
                                    CASE    
                                        WHEN E.Modalidades=''CR''
                                            THEN ''Radiología Simple''                  
                                        WHEN E.Modalidades=''DX''
                                            THEN ''Radiología Simple''
                                        WHEN E.Modalidades=''MG''
                                            THEN ''Mastografía''
                                        WHEN E.Modalidades=''BDUS'' OR E.Modalidades=''BMD''
                                            THEN ''Densitometría''
                                        WHEN E.Modalidades=''RF''
                                            THEN ''Radiología Contrastada''
                                        WHEN E.Modalidades=''US''
                                            THEN    (
                                                        CASE
                                                            WHEN E.Descripcion NOT LIKE ''%DOPPLER%'' /*OR E.Descripcion NOT LIKE ''%DOPLER%''*/ THEN ''Ultrasonido''
                                                            WHEN E.Descripcion LIKE ''%DOPPLER%'' OR E.Descripcion LIKE ''%DOPLER%'' THEN ''Ultrasonido Doppler''
                                                        ELSE ''Ultrasonido''
                                            END     )
                                        WHEN E.Modalidades=''CT''
                                            THEN    (
                                                        CASE
                                                            WHEN E.Descripcion NOT LIKE ''%CONTRAST%'' THEN ''Tomografía Computada Simple''
                                                            WHEN E.Descripcion  LIKE ''%CON CONTRASTE%'' OR E.Descripcion LIKE ''%CONTRASTADO%'' OR E.Descripcion LIKE ''%CONTRASTADA%'' OR E.Descripcion LIKE ''%GADOLIN%'' THEN ''Tomografía Computada con medio de Contraste''
                                                        ELSE ''Tomografía Computada Simple''                                
                                            END     )
                                        WHEN E.Modalidades=''MR''
                                            THEN    (
                                                        CASE
                                                            WHEN E.Descripcion NOT LIKE ''%CONTRAST%'' THEN ''Resonancia Magnética Simple''
                                                            WHEN E.Descripcion  LIKE ''%CON CONTRAST%'' OR E.Descripcion LIKE ''%CONTRASTADO%'' OR E.Descripcion LIKE ''%CONTRASTADA%'' OR E.Descripcion LIKE ''%GADOLIN%'' THEN ''Resonancia Magnética Contrastada''
                                                        ELSE ''Resonancia Magnética Simple''
                                            END     )
                                        WHEN E.Modalidades=''XA''
                                            THEN ''RADIOLOGIA INTERVENCIONISTA VASCULAR''
                                        WHEN E.Modalidades=''ES''
                                            THEN ''RADIOLOGIA INTERVENCIONISTA NO VASCULAR''
                                        ELSE ''OTRAS MODALIDADES DICOM''
                                    END AS TIPO_DE_ESTUDIO,
                                    E.Modalidades AS MODALIDAD,
                                    CASE
                                        WHEN I_R_E.IdEstadoResultado IN (0,1,2)
                                            THEN ''SIN INTERPRETACION''
                                        ELSE CONVERT(VARCHAR,I_R_E.FechaResultado,103)
                                    END AS RESULTADO
                                FROM
                                    DBO.Pacientes AS P
                                INNER JOIN
                                    DBO.ImagenologiaEstudios AS E ON P.IDPACIENTE=E.IdPaciente
                                LEFT JOIN
                                    dbo.ImagenologiaResultadosEstudio AS I_R_E ON E.IdEstudio=I_R_E.IdEstudio AND E.IdEstudio=I_R_E.IdEstudio
                                WHERE
                                    E.FechaEstudio BETWEEN ' + '''' + CONVERT(VARCHAR,@FechaInicio,121) + '''' +  ' AND ' + '''' + CONCAT(CONVERT(VARCHAR,@FechaInicio,23),' 23:59:59.999') + '''' +  ' AND E.VisiblePACS = 1
                        ) AS T
                        GROUP BY
                            T.IdPaciente,
                            T.UIDESTUDIO,
                            T.FECHA_DEL_ESTUDIO,
                            T.UNIDAD_TRATANTE,
                            T.ApellidoPaterno,
                            T.ApellidoMaterno,
                            T.NOMBRE_DEL_PACIENTE,
                            T.NSS,
                            T.CLAVE_CPIM,
                            T.AGREGADO_MEDICO,
                            T.TIPO_DE_ESTUDIO,
                            T.MODALIDAD,
                            T.RESULTADO
                        HAVING
                            COUNT(T.UIDESTUDIO) >= 1
                    ) AS R
            ) AS WW 
        ) AS XX
                    )
        INSERT INTO HIS_CORTES_UDDCM.dbo.CORTE_MES_EJEMPLO (
            [PACIENTE_nVECES_REPETIDOS],[FECHA_DEL_ESTUDIO],[UNIDAD_TRATANTE],[ApellidoPaterno],[ApellidoMaterno],[NOMBRE_DEL_PACIENTE],[NSS],[CLAVE_CPIM],[AGREGADO_MEDICO],[TIPO_DE_ESTUDIO],[MODALIDAD],[INTERPRETACION],[PARTICION_UID])
        SELECT
            TOP 1000 [PACIENTE_nVECES_REPETIDOS],[FECHA_DEL_ESTUDIO],[UNIDAD_TRATANTE],[ApellidoPaterno],[ApellidoMaterno],[NOMBRE_DEL_PACIENTE],[NSS],[CLAVE_CPIM],[AGREGADO_MEDICO],[TIPO_DE_ESTUDIO],[MODALIDAD],[INTERPRETACION],[PARTICION_UID]
        FROM
            CTE_CORTES
        WHERE
            CTE_CORTES.PARTICION_UID=1
        ORDER BY
            CTE_CORTES.NSS, CTE_CORTES.FECHA_DEL_ESTUDIO'
    SET @FechaInicio += 1
    PRINT '/*#######################################################################################SALTO DE DIA#######################################################################################*/'
END

整个脚本依赖于几乎对数据集进行分区的一行代码(我使用ROW_NUMBER 并嵌套SUBSTRING 函数),ID 和日期的排序由@ 负责987654331@ 子句(与ROW_NUMBER 窗口函数一样重要)。

这是我指的那一行:

这基本上是采用 ID 列(字符串)并最多包含 10 个字符。如果 ID 列行中的前 10 个字符之间存在相似性,则ROW_NUMBER 函数将每一行从 1 到一天内发现的重合数进行分组/枚举(不能超过一天。因为如果确实如此, 数据不再可靠。这就是上面的脚本使用WHILE循环逐日插入数据的原因。

这是执行 TSQL 脚本后表格的样子:

如果您密切注意第一列和以蓝色突出显示的行,您会看到我所说的按集进行的分区/分组正在执行。行和 ID 已按日期和 ID(升序)以有组织的方式排序/排序。 ID 之间的相似性显示在 nTIMES_ID_REPEATED 列中。主要关注以蓝色突出显示的行。这些是符合我将要解释的标准的那些。以黄色突出显示的也符合条件(相似性),但由于它们各自的 REPORT_STATUS 列(日期类型)为空,因此无法考虑。

现在,这就是挑战所在(老实说,我不知道如何应对这一挑战)。基于使用 nTIMES_ID_REPEATED 列完成的分区/分组,我的任务是访问这些行(显示 1、2、3 直到最后一个数字的行)并执行(可能)另一个窗口函数来只要它们各自的 REPORT_STATUS 列不为空,就再次列出它们(将它们显示在不同的列上)。

期望的结果应该是这样的:

尽管ROW_COUNTSUBSTRING 函数找到了更多匹配项(nTIMES_ID_REPEATED 列),但不能考虑黄色行,因为它的 REPORT_STATUS 列是空的。基本上它们应该被忽略。

顺便说一句,我制作了一个虚拟表,并为那些想在sqlfiddle尝试的人填充了相同的挑战:

CREATE TABLE TEST_TABLE ( 
    nTIMES_ID_REPEATED INT,
    STUDY_DATE DATETIME,
    HOSPITAL varchar(255),
    FIRST_LAST_NAME varchar(255),
    SECOND_LAST_NAME varchar(255),
    PATIENT_NAME varchar(255),
    NSS varchar(255),
    CPIM_CODE varchar(255),
    ID_REMAINDER varchar(255),
    STUDY_TYPE varchar(255),
    MODALITY varchar(255),
    REPORT_STATUS varchar(255),
    UID_PARTITION INT

            );


INSERT INTO TEST_TABLE VALUES (1,'2022/05/28','HGZ 98','SANCHEZ','GONZALEZ','DANIELA YARELI ','9211929411','80.15.005','1F1992OR','Ultrasonido','US','28/05/2022',1)
INSERT INTO TEST_TABLE VALUES (2,'2022/05/28','HGZ 98','SANCHEZ','GONZALEZ','DANIELA YARELI ','9211929411','80.15.005','1F1992OR','Ultrasonido','US','28/05/2022',1)
INSERT INTO TEST_TABLE VALUES (1,'2022/05/28','HGZ 98','AVILA','ESPINOZA','MA DE JESUS ','9409850742','80.15.005','4F1961OR','Ultrasonido','US','28/05/2022',1)
INSERT INTO TEST_TABLE VALUES (2,'2022/05/28','HGZ 98','AVILA','ESPINOZA','MA DE JESUS ','9409850742','80.15.005','4F1961OR','Ultrasonido','US','28/05/2022',1)
INSERT INTO TEST_TABLE VALUES (1,'2022/05/28','HGZ 98','VELAZQUEZ','CONTRERAS','GRECIA IRLANDA ','9412972424','80.15.005','1F1997OR','Ultrasonido','US','28/05/2022',1)
INSERT INTO TEST_TABLE VALUES (2,'2022/05/28','HGZ 98','VELAZQUEZ','CONTRERAS GRECIA IRLANDA',' ','9412972424','80.15.001','00000000','Radiología Simple','CR',' ',1)
INSERT INTO TEST_TABLE VALUES (1,'2022/05/28','HGZ 98','SANTIAGO','ARREDONDO','HANNA NIDIA ','9496811863','80.15.005','3F2008OR','Ultrasonido','US','28/05/2022',1)
INSERT INTO TEST_TABLE VALUES (2,'2022/05/28','HGZ 98','SANTIAGO','ARREDONDO HANNA NIDIA',' ','9496811863','80.15.001','10000000','Radiología Simple','CR',' ',1)
INSERT INTO TEST_TABLE VALUES (3,'2022/05/28','HGZ 98','SANTIAGO','ARREDONDO HANNA NIDIA',' ','9496811863','80.15.007','13F2008O','Tomografía Computada Simple','CT','28/05/2022',1)
INSERT INTO TEST_TABLE VALUES (1,'2022/05/28','HGZ 98','PACHECO','PINEDA ISABEL',' ','9498790021','80.15.001','20000000','Radiología Simple','CR',' ',1)
INSERT INTO TEST_TABLE VALUES (2,'2022/05/28','HGZ 98','PACHECO','PINEDA ISABEL',' ','9498790021','80.15.001','70000000','Radiología Simple','CR',' ',1)

可以用窗口函数完成还是我必须以不同的方式解决这个问题?提前致谢。

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    我相信这两种方法都能奏效。您可能会发现其中一个比另一个表现更好:

    case when report_status is not null then
        row_number() over (
            partition by <ID>
            order by case when report_status is not null then 1 end, <date>) end
    

    或者

    case when report_status is not null then
        row_number() over (
            partition by <ID>, case when report_status is not null then 1 end
            order by <date>) end
    

    【讨论】:

      猜你喜欢
      • 2019-07-08
      • 2017-07-31
      • 2016-01-27
      • 1970-01-01
      • 1970-01-01
      • 2021-02-05
      • 2013-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多