perf: 제품 검색 최적화 - 사용약품만 옵션 추가
문제: 전체 CD_GOODS 검색 시 178,232건 스캔 + OUTER APPLY → 6-14초 소요 해결: - '사용약품만' 체크박스 추가 (기본 활성화) - IM_total INNER JOIN으로 재고 있는 2,810건만 검색 - OUTER APPLY 제거로 쿼리 단순화 성능: 6.5초 → 1.4초 (4.6배 향상)
This commit is contained in:
@@ -3306,10 +3306,12 @@ def api_products():
|
||||
제품 검색 API
|
||||
- 상품명, 상품코드, 바코드로 검색
|
||||
- 세트상품 바코드도 CD_ITEM_UNIT_MEMBER에서 조회
|
||||
- in_stock_only: 사용약품만 (IM_total에 재고 있는 제품)
|
||||
"""
|
||||
search = request.args.get('search', '').strip()
|
||||
limit = int(request.args.get('limit', 100))
|
||||
animal_only = request.args.get('animal_only', '0') == '1'
|
||||
in_stock_only = request.args.get('in_stock_only', '0') == '1'
|
||||
|
||||
if not search or len(search) < 2:
|
||||
return jsonify({'success': False, 'error': '검색어는 2글자 이상 입력하세요'})
|
||||
@@ -3317,43 +3319,66 @@ def api_products():
|
||||
try:
|
||||
drug_session = db_manager.get_session('PM_DRUG')
|
||||
|
||||
# 제품 검색 쿼리
|
||||
# CD_GOODS.BARCODE가 없으면 CD_ITEM_UNIT_MEMBER.CD_CD_BARCODE 사용 (세트상품)
|
||||
# 세트상품 여부 확인: CD_item_set에 SetCode로 존재하면 세트상품
|
||||
products_query = text(f"""
|
||||
SELECT TOP {limit}
|
||||
G.DrugCode as drug_code,
|
||||
G.GoodsName as product_name,
|
||||
COALESCE(NULLIF(G.BARCODE, ''), U.CD_CD_BARCODE, '') as barcode,
|
||||
G.Saleprice as sale_price,
|
||||
G.Price as cost_price,
|
||||
CASE
|
||||
WHEN G.SplName IS NOT NULL AND G.SplName != '' THEN G.SplName
|
||||
WHEN SET_CHK.is_set = 1 THEN N'세트상품'
|
||||
ELSE ''
|
||||
END as supplier,
|
||||
CASE WHEN SET_CHK.is_set = 1 THEN 1 ELSE 0 END as is_set,
|
||||
G.POS_BOON as pos_boon,
|
||||
ISNULL(IT.IM_QT_sale_debit, 0) as stock
|
||||
FROM CD_GOODS G
|
||||
LEFT JOIN IM_total IT ON G.DrugCode = IT.DrugCode
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 CD_CD_BARCODE
|
||||
FROM CD_ITEM_UNIT_MEMBER
|
||||
WHERE DRUGCODE = G.DrugCode AND CD_CD_BARCODE IS NOT NULL AND CD_CD_BARCODE != ''
|
||||
) U
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 1 as is_set
|
||||
FROM CD_item_set
|
||||
WHERE SetCode = G.DrugCode AND DrugCode = 'SET0000'
|
||||
) SET_CHK
|
||||
WHERE
|
||||
G.GoodsName LIKE :search_like
|
||||
OR G.DrugCode LIKE :search_like
|
||||
OR G.BARCODE LIKE :search_like
|
||||
OR U.CD_CD_BARCODE LIKE :search_like
|
||||
ORDER BY G.GoodsName
|
||||
""")
|
||||
# 제품 검색 쿼리 - 사용약품만 옵션에 따라 JOIN 방식 변경
|
||||
# in_stock_only: INNER JOIN으로 재고 있는 제품만 (빠름)
|
||||
# 그렇지 않으면: LEFT JOIN으로 모든 제품 (느림)
|
||||
if in_stock_only:
|
||||
# 최적화된 쿼리: 재고 있는 제품만 (IM_total INNER JOIN)
|
||||
products_query = text(f"""
|
||||
SELECT TOP {limit}
|
||||
G.DrugCode as drug_code,
|
||||
G.GoodsName as product_name,
|
||||
COALESCE(NULLIF(G.BARCODE, ''), '') as barcode,
|
||||
G.Saleprice as sale_price,
|
||||
G.Price as cost_price,
|
||||
ISNULL(G.SplName, '') as supplier,
|
||||
0 as is_set,
|
||||
G.POS_BOON as pos_boon,
|
||||
IT.IM_QT_sale_debit as stock
|
||||
FROM CD_GOODS G
|
||||
INNER JOIN IM_total IT ON G.DrugCode = IT.DrugCode AND IT.IM_QT_sale_debit > 0
|
||||
WHERE
|
||||
G.GoodsName LIKE :search_like
|
||||
OR G.DrugCode LIKE :search_like
|
||||
OR G.BARCODE LIKE :search_like
|
||||
ORDER BY G.GoodsName
|
||||
""")
|
||||
else:
|
||||
# 전체 쿼리 (OUTER APPLY 포함, 느림)
|
||||
products_query = text(f"""
|
||||
SELECT TOP {limit}
|
||||
G.DrugCode as drug_code,
|
||||
G.GoodsName as product_name,
|
||||
COALESCE(NULLIF(G.BARCODE, ''), U.CD_CD_BARCODE, '') as barcode,
|
||||
G.Saleprice as sale_price,
|
||||
G.Price as cost_price,
|
||||
CASE
|
||||
WHEN G.SplName IS NOT NULL AND G.SplName != '' THEN G.SplName
|
||||
WHEN SET_CHK.is_set = 1 THEN N'세트상품'
|
||||
ELSE ''
|
||||
END as supplier,
|
||||
CASE WHEN SET_CHK.is_set = 1 THEN 1 ELSE 0 END as is_set,
|
||||
G.POS_BOON as pos_boon,
|
||||
ISNULL(IT.IM_QT_sale_debit, 0) as stock
|
||||
FROM CD_GOODS G
|
||||
LEFT JOIN IM_total IT ON G.DrugCode = IT.DrugCode
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 CD_CD_BARCODE
|
||||
FROM CD_ITEM_UNIT_MEMBER
|
||||
WHERE DRUGCODE = G.DrugCode AND CD_CD_BARCODE IS NOT NULL AND CD_CD_BARCODE != ''
|
||||
) U
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1 1 as is_set
|
||||
FROM CD_item_set
|
||||
WHERE SetCode = G.DrugCode AND DrugCode = 'SET0000'
|
||||
) SET_CHK
|
||||
WHERE
|
||||
G.GoodsName LIKE :search_like
|
||||
OR G.DrugCode LIKE :search_like
|
||||
OR G.BARCODE LIKE :search_like
|
||||
OR U.CD_CD_BARCODE LIKE :search_like
|
||||
ORDER BY G.GoodsName
|
||||
""")
|
||||
|
||||
search_like = f'%{search}%'
|
||||
rows = drug_session.execute(products_query, {
|
||||
|
||||
Reference in New Issue
Block a user