2017-09-08 2 views
0

에 별개로 다중 테이블 쿼리에 행 집계는 내가 기능적으로 함께 밀어 노력하고 쿼리의 다소 복잡한 쌍을 가지고있다.PostgreSQL의 :

처음에는 (설문 조사 쿼리)이며 6 개의 테이블에서 다양한 인구 통계 및 방문 정보를 선택합니다. 그것의 중앙에있는 방문 ID 번호 방문 테이블에 대한 방문 ID 번호 각 방문 ID 및 각 방문 인구 통계 정보에 대한 행을 반환

두 번째 쿼리 (프로 시저 쿼리) 5 테이블을 조인하고 또한 방문 테이블에 가입됩니다. 각 방문 대신 프로 시저 코드마다 줄을 반환합니다.

나는 5 별도의 열로 배열에 각 방문에 대한 절차를 시도하고 설문 조사 쿼리의 결과로이 문제를 포함하고있다.

우리가 사용하는 현재 프로 시저 쿼리.

Procedure Query 

SELECT D 
    DISTINCT ON ("public".patient_procedure.pproc_visit_num, 
        "public".procedure_group_cpt_code.pgrpcpt_code) 

"public".visit.visit_id AS "Patient ID", 
("public".procedure_group_cpt_code.pgrpcpt_code) AS "Procedure Code" 

FROM 
"public".patient_procedure 
LEFT JOIN "public".procedure_desc_master_codes ON "public".patient_procedure.pproc_cpcode = "public".procedure_desc_master_codes.pdescm_id 
LEFT JOIN "public".procedure_group_cpt_code ON "public".procedure_desc_master_codes.pdescm_id = "public".procedure_group_cpt_code.pgrpcpt_pdescm_id 
LEFT JOIN "public".procedure_group_snomed_codes ON "public".procedure_desc_master_codes.pdescm_id = "public".procedure_group_snomed_codes.pgrpsnomed_pdescm_id 
LEFT JOIN "public".visit ON "public".patient_procedure.pproc_visit_num = "public".visit.visit_id 
LEFT JOIN "public".physician_table1 ON "public".patient_procedure.pproc_proc_phy1 = "public".physician_table1.phys1_num 


ORDER BY 
"public".patient_procedure.pproc_visit_num 

.

결과는

Patient id procedure code 
-----------|------------------------ 
    1  | A34 
    1  | B23 
    1  | C43 
    2  | F12 
    3  | A34 
    3  | E65  
    4  | T55  
    4  | U67 

처럼 보인다.

나는 다음과 같은 세인 것을

를 사용 Array_agg 절차 코드에 대한를 사용하여 시도했다.

SELECT 
    DISTINCT ON ("public".patient_procedure.pproc_visit_num) 
    "public".visit.visit_id AS "Patient ID", 
    array_agg("public".procedure_group_cpt_code.pgrpcpt_code) AS "Procedure Code" 

FROM 
"public".patient_procedure 
LEFT JOIN "public".procedure_desc_master_codes ON "public".patient_procedure.pproc_cpcode = "public".procedure_desc_master_codes.pdescm_id 
LEFT JOIN "public".procedure_group_cpt_code ON "public".procedure_desc_master_codes.pdescm_id = "public".procedure_group_cpt_code.pgrpcpt_pdescm_id 
LEFT JOIN "public".procedure_group_snomed_codes ON "public".procedure_desc_master_codes.pdescm_id = "public".procedure_group_snomed_codes.pgrpsnomed_pdescm_id 
LEFT JOIN "public".visit ON "public".patient_procedure.pproc_visit_num = "public".visit.visit_id 
LEFT JOIN "public".physician_table1 ON "public".patient_procedure.pproc_proc_phy1 = "public".physician_table1.phys1_num 


group by 
"public".visit.visit_id, 
"public".patient_procedure.pproc_visit_num, 
"public".procedure_group_cpt_code.pgrpcpt_code 


ORDER BY 
"public".patient_procedure.pproc_visit_num 

array_agg 함수를 사용하면 결과는 다음과 같습니다. 첫 번째 값 복제. 나는 테이블/결과에서 환자 ID가 발생할 때마다 추정합니다.

. .

Patient id procedure code 
-----------|------------------------ 
    1  | {A34,A34,A34,A34,A34} 
    1  | {B23,B23,B23,B23,B23,} 
    1  | {C43,C43} 
    2  | {F12,F12} 
    3  | {A34} 
    3  | {E65,E65,E65,E65,E65,E65,E65,E65,} 
    4  | {T55,T55,T55,T55,} 

설문 조사 쿼리, 내가 두 번째 쿼리에 포함 된 절차를 가지고 할 수있는 방법이 무엇인지 중간

select 
distinct on ("public".visit.visit_id) 
rpad('1.6.1', 5, '') AS "Survey Designator", 
rpad('1.6.1', 5, '') AS "Client ID", 
"public".profile.prof_c_ip1lastname AS "Last Name", 
left("public".profile.prof_c_ip1midname,1) AS "Middle Initial", 
"public".profile.prof_c_ip1firstname AS "First Name", 
"public".profile.prof_c_ip1p_addr1 AS "Address 1", 
"public".profile.prof_c_ip1p_addr2 AS "Address 2", 
"public".profile.prof_c_ip1p_city AS "City", 
"public".profile.prof_c_ip1p_state AS "State", 


CASE 
WHEN "public".profile.prof_c_ip1p_zip = 0 THEN '' 
ELSE "public".profile.prof_c_ip1p_zip::text 
END AS "ZIP Code", 


CASE 
WHEN "public".profile.prof_c_arpphone = 0 THEN '' 
ELSE "public".profile.prof_c_arpphone::text 
END AS "Telephone Number", 


CASE WHEN "public".profile.prof_c_ip1p_cell = 0 THEN '' 
ELSE "public".profile.prof_c_ip1p_cell::text 
END AS "Mobile Number", 

rpad('1.6.1', 5, '') AS "MS-DRG", 


CASE "public".profile.prof_c_arpsex 
when 'M' THEN '1' 
WHEN 'F' THEN '2' 
ELSE 'M' 
END AS "Gender", 

to_char("public".visit.visit_date_of_birth, 'MMDDYYYY') AS "Date of Birth", 



case LOWER("public".profile.prof_c_ip1language_code) 
WHEN 'eng' Then '0' 
WHEN 'spa' then '1' 
ELSE 'U' 
END AS "Preferred Language Code", 

"public".visit.visit_mr_num AS "Medical Record Number", 
"public".visit.visit_id as "Unique Id", 
"public".physician_table1.phys1_npi AS "Attending Physician NPI", 
"public".physician_table1.phys1_name AS "Attending Physician Name", 

CASE "public".ip_visit_1.ipv1_origin 
WHEN '1' THEN '1' 
WHEN '2' THEN '2' 
WHEN '3' THEN '6' 
WHEN '5' THEN '8' 
ELSE '9' 
END AS "Admission Source", 

to_char("public".visit.visit_admit_date, 'MMDDYYYY') AS "Visit or Admit Date", 
to_char("public".visit.visit_disch_date, 'MMDDYYYY') AS "Discharge Date", 


CASE WHEN "public".ip_visit_1.ipv1_p_email LIKE '%@%' 
THEN "public".ip_visit_1.ipv1_p_email ELSE '' 
END AS "Email", 


CASE "public".visit.visit_admit_phy_key 
when '000215' then '1518958503' 
when '002515' then '1770546756' 
when '003700' then '1255362448' 
else '' 
end as "Hospitalist 1", 

CASE "public".ip_visit_1.ipv1_phy2 
when '000215' then '1518958503' 
when '002515' then '1770546756' 
when '003700' then '1255362448' 
else '' 
end as "Hospitalist 2", 


case "public".er_log.cnerlog_admdt 
when '0001-01-01' then 'N' 
else 'Y' 
end as "ER_ADMIT", 

--somehow get procedures in here, 


case "public".profile.prof_c_ip1expired_dt 
when '0001-01-01' then 'N' 
when null then 'N' 
else 'Y' 
End as "Deceased Flag", 
rpad('N', 1, '') AS "State Regulation Flag", 

case when "public".visit.visit_date_of_birth > ("public".visit.visit_admit_date - interval '29' day) then 'Y' 
else 'N' 
end as "Newborn patient", 



rpad('$', 1, '') AS "E.O.R Indicator" 
FROM 
"public".visit 
INNER JOIN "public".profile ON "public".profile.prof_c_arpmrnum = "public".visit.visit_mr_num 
INNER JOIN "public".physician_table1 ON "public".visit.visit_admit_phy_key = "public".physician_table1.phys1_num 
INNER JOIN "public".ip_visit_1 ON "public".ip_visit_1.ipv1_num = "public".visit.visit_id 
left JOIN "public".patient_procedure ON "public".visit.visit_id = "public".patient_procedure.pproc_visit_num 
left JOIN "public".procedure_desc_master_codes ON "public".patient_procedure.pproc_cpcode = "public".procedure_desc_master_codes.pdescm_id 
left JOIN "public".procedure_group_cpt_code ON "public".procedure_desc_master_codes.pdescm_id = "public".procedure_group_cpt_code.pgrpcpt_pdescm_id 
left JOIN "public".er_log ON "public".er_log.cnerlog_patnum = "public".visit.visit_id 

order BY 
"public".visit.visit_id asc 

limit 10000 

으로 절차를 밀어 싶습니다? 심지어 쿼리가 매주에게

감사

를 실행하는 것입니다으로 빠르게 될 필요가 없습니다 ++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++ 편집 을 추가 +++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++

프로 시저 코드에서. 집계 된 열에서 많은 중복을 얻었지만 여전히 괜찮습니다. 내가 밖으로 것을 알 수 있습니다 다음

SELECt 
"public".visit.visit_id as "visit ID", 
string_agg("public".procedure_group_cpt_code.pgrpcpt_code::text, ', ') AS "CPT4/HCPCS Code" 

FROM 
"public".patient_procedure 
LEFT JOIN "public".procedure_desc_master_codes ON "public".patient_procedure.pproc_cpcode = "public".procedure_desc_master_codes.pdescm_id 
LEFT JOIN "public".procedure_group_cpt_code ON "public".procedure_desc_master_codes.pdescm_id = "public".procedure_group_cpt_code.pgrpcpt_pdescm_id 
LEFT JOIN "public".visit ON "public".patient_procedure.pproc_visit_num = "public".visit.visit_id 

WHERE 
"public".patient_procedure.pproc_date BETWEEN '2017-07-01' AND '2017-07-31' AND 
"public".patient_procedure.pproc_visit_num NOT LIKE 'C%' 

GROUP BY 
"public".visit.visit_id 
ORDER BY 
"public".visit.visit_id 

이, 더 나은 작동 배열 값으로 열을두고 array_agg와 중복 제거 (별개의 "가치")

SELECt 
"public".visit.visit_id as "visit ID", 
array_agg(distinct "public".procedure_group_cpt_code.pgrpcpt_code::text) AS "CPT4/HCPCS Code" 

FROM 
"public".patient_procedure 
LEFT JOIN "public".procedure_desc_master_codes ON "public".patient_procedure.pproc_cpcode = "public".procedure_desc_master_codes.pdescm_id 
LEFT JOIN "public".procedure_group_cpt_code ON "public".procedure_desc_master_codes.pdescm_id = "public".procedure_group_cpt_code.pgrpcpt_pdescm_id 
LEFT JOIN "public".visit ON "public".patient_procedure.pproc_visit_num = "public".visit.visit_id 

WHERE 
"public".patient_procedure.pproc_date BETWEEN '2017-07-01' AND '2017-07-31' AND 
"public".patient_procedure.pproc_visit_num NOT LIKE 'C%' 

GROUP BY 
"public".visit.visit_id 
ORDER BY 
"public".visit.visit_id 

답변

0

나는이 내가 같은 문제를 참조 상황이 그들이 필요로하는 것보다 더 복잡하다고 생각하는 경향이 있습니다.두 쿼리를 통합하면 성능이 떨어지고 유지 관리가 최적이되지 않을 가능성이 있습니다.

일들이 Distinct On 및 집계로 올바르게 작동하지 않을 때, 대신 GROUP BY을 원할 가능성이 있습니다. 이것들은 완전히 다른 두 가지 일을하지만, GROUP BY은 집합체로 훨씬 잘 작동합니다. 이런 복잡한 경우

은주의해야 할 몇 가지 중요한 단축키가 있습니다 : 당신이 집계의 원자 일부를 형성 무엇을 테이블 결정할 때

  • 을 수행 할 수 있습니다 이러한 테이블과 테이블의 group by 기본 키 이를 외부로 참조하여 사용 된 모든 열을 그룹화 할 필요가 없습니다.
  • 이렇게하면 수동으로 처리해야하는 데이터베이스 디자인의 특정 모호성이나 문제점을 발견하게됩니다.

또한 PostgreSQL에서는 창 기능 (점진적으로 적용되는 집계)과 이러한 경우에도 도움이되는 공통 테이블 표현식이 있음을 기억하십시오.

내 권장 사항은 종이에 관계를 매핑하고, 원하는 데이터를 파악하고, 집계의 기준으로 어떤 테이블을 사용하는지 결정합니다 (즉, 해당 테이블의 한 행이 귀하의 출력) 다음 대신 group by을 사용하여보십시오

이것이 충분하지 않은 경우 데이터를 매핑하고 원하는 것을 밖으로, 당신은 어떻게 얻을 수있는 질문에 더 나은 위치에있을 것입니다 당신이 SQL에서 원하는 것.

+0

대부분 배기 - >> 그래서 나는 당신의 제안을 시도하고 있습니다. 이 데이터베이스에 뛰어 들어올 때마다 나는 그다지 숙련되지 않은 사람들에 의해 설계되고 만들어졌습니다. 모든 단일 테이블에는 최소한 3 개의 키가 있습니다. 4200 개의 고유 테이블을 곱하십시오. . . 또한 나는 열쇠로 당신의 그룹을 시험해보고 있는데, 내가 할 수있는 일이 무엇인지 몰랐고, 내 질문을 올바른 방향으로 밀고있는 것처럼 보입니다. –