처음 처음 | 이전 이전 | 1 | 2 | 3 | 4 |다음 다음 | 마지막 마지막
대신 주식해드립니다 - S대 경제·심리 전공 17년 차 감성 투자자의 손실 방지책
이민수(입금완료) 지음 / 알에이치코리아(RHK) / 2026년 2월
평점 :
장바구니담기


주식투자로 실패할 수 있는 모든 경험을 고급스러운 해학으로 잘 풀어낸 책입니다.
이 책에서 얻을 것이 있다면, 함부로 귀동냥으로 투자하면 백전백패 한다는 것이겠죠. https://buly.kr/EoqSvU3

댓글(2) 먼댓글(0) 좋아요(0)
좋아요
l 공유하기 l 북마크하기찜하기 lthankstoThanksTo
 
 
2026-07-29 12:41   URL
비밀 댓글입니다.

데이터인사이트 2026-10-13 11:12   좋아요 0 | 댓글달기 | URL
표준구분 공장 적재순번 소스테이블2 소스테이블 소스테이블 특이사항 소스컬럼 컬럼특이사항 타겟테이블 타겟컬럼 속성명 컬럼순서 쿼리 쿼리 하나로 쿼리테이블 WHERE T1 T2 T3 T4 T2조인 T3조인

소스컬럼열
=LET( 컬럼, IFERROR(XLOOKUP(1, ([@소스테이블2] = 타공장컬럼[표준테이블명1]) *( [@타겟테이블] = 타공장컬럼[DW테이블명]) * ( [@타겟컬럼] = 타공장컬럼[DW컬럼명]), 타공장컬럼[원본컬럼함수]), ˝NULL˝),
플랜트번호, ˝‘˝& XLOOKUP( [@공장], 쿼리[공장명], 쿼리[플랜트번호]) & ˝‘˝,
IF([@타겟컬럼]= ˝PLANT_NO˝, 플랜트번호, 컬럼 ) )


쿼리열
=LET(
소스팩토리, $B8591,
쿼리주석, ˝--˝& $C8591 &˝.˝&[@타겟테이블]&˝(˝&[@공장]&˝,˝&[@소스테이블2]&˝)˝&CHAR(10),
공백, ˝˝,
소스테이블, $D8591,
쿼리타입, $F8591,
소스컬럼, $G8591,
컬럼특이사항, $H8591,
타겟테이블, $I8591,
타겟컬럼, $J8591,
속성명, $K8591,
컬럼순서, $L8591,
T2테이블적용, $R8591,
T3테이블적용, $S8591,
줄바꿈, CHAR(10),

테이블접두사,
IF(컬럼특이사항=˝삭제˝,˝˝,
IF(AND(T3테이블적용=˝˝, 컬럼특이사항<>˝˝), 소스컬럼,
IF(T3테이블적용<>˝˝,˝T3.˝&소스컬럼,
IF(T2테이블적용<>˝˝,˝T2.˝&소스컬럼,˝T1.˝&소스컬럼)
)
)
),

선택컬럼, 테이블접두사 & 공백 & ˝ as ˝&타겟컬럼& 공백 & ˝ -- ˝&속성명,

INSERT문, XLOOKUP(소스팩토리,쿼리[공장명],쿼리[인서트문],˝˝),
파티션문, XLOOKUP(소스팩토리,쿼리[공장명],쿼리[파티션문],˝˝),

WHERE조건, XLOOKUP(1,($D$2737:$D$13410=소스테이블)*($I$2737:$I$13410=타겟테이블)*($L$2737:$L$13410=1)*($B$2737:$B$13410=소스팩토리),$O$2737:$O$13410,˝˝),
WHERE추가절, XLOOKUP(1,($D$2737:$D$13410=소스테이블)*($I$2737:$I$13410=타겟테이블)*($L$2737:$L$13410=1)*($B$2737:$B$13410=소스팩토리),$P$2737:$P$13410,˝˝),

IF(컬럼특이사항=˝삭제˝,
˝-- 삭제컬럼 ˝&타겟컬럼,

IF(AND(쿼리타입=˝SELECT˝,컬럼순서=1),
˝ SELECT ˝&선택컬럼,

IF(OR(AND(쿼리타입=˝INSERT˝,컬럼순서=1),AND(쿼리타입=˝˝,컬럼순서=1)),
쿼리주석&줄바꿈&INSERT문&타겟테이블&줄바꿈&파티션문&줄바꿈&˝ SELECT ˝&선택컬럼,

IF(AND(쿼리타입=˝UNION ALL˝,컬럼순서=1),
˝UNION ALL ˝&줄바꿈&쿼리주석&줄바꿈&˝ select ˝&선택컬럼,

IF(소스팩토리&소스테이블&타겟테이블=$B8592&$D8592&$I8592,
˝, ˝&선택컬럼,
˝, ˝&선택컬럼&˝ ˝&줄바꿈&WHERE조건&줄바꿈&WHERE추가절
)
)
)
)
)
)


쿼리하나로
=TEXTJOIN(CHAR(10), TRUE, IF(($B$2737:$B$12044=$B8582)*($D$2737:$D$12044=$D8582)*($I$2737:$I$12044=$I8582), $M$2737:$M$12044, ˝˝))


쿼리테이블
=˝FROM ˝ & IFERROR(IF(AND(U8582<>˝˝, L8582 = 1),
$Q8582& ˝ T1˝&CHAR(10)&U8582&CHAR(10)&V8582,
$Q8582& ˝ T1˝), ˝˝)


where 열
=CONCAT(˝WHERE 1=1˝, CHAR(10),
˝AND T1.ldg_ymd = ˝, XLOOKUP([@공장],쿼리[공장명],쿼리[소스적재일자], CHAR(10) ))
 
김앤북 내일은 데이터분석 준전문가(ADsP)
Jade Jeong 지음 / 아이비김영(김앤북) / 2024년 7월
평점 :
장바구니담기


총 342페이지에 개념정리만 212페이지이어서 처음엔 너무 내용이 빈약한 것이 아닐까 하였으나,

기존의 유명했던 책으로 공부해서 자격증을 합격한 입장에서 

너무 많은 설명으로 인한 읽기의 피로감이 아쉬웠고, 시험에 나온 내용은 설명이 부족했던 기억이 있어서

좀 더 간략하게 정리잘 된, 그리고 핵심개념은 빠지지 않는 

자격증 도서가 있었으면 했는데, 

이 책은 최근 수험생의 요구사항을 잘 받아들여서 인지 

기존 책의 부족한 면을 잘 채워주는 부분이 많았습니다. 


■ 이 책의 장점

 1. 시험에 자주 출제되는 개념에 대해서 잘 정리되어 있습니다. 

 2. 이해가 어려운 내용은 그림이나 도표로 좀 더 시각화하여 알려줍니다. 

 3. 연습문제에서 부족한 내용을 보강하여 설명합니다. 

 4. 기출문제에서 결과 해석문제에 대한 설명이 잘 되어 있습니다. 

 

 

■ 기출문제 

  36회 ~ 40회까지 기출문제가 책에 수록되어 있고, 41회는 온라인으로 제공합니다. 

  44회 대비하여 최신 문제가 없긴 하지만, 41회까지 기출문제와 해설을 이해한다면 

  어떤 회차의 시험도 합격할 수준이 되리라 봅니다. 


■ 총평

 기출문제를 풀면서 모르는 개념만을 확인하면서 2주만에 합격하고자 하는 계획도 괜찮겠고

 이론이 부족하다면, 개념에 대하여 빠르게 1회 정독하고 기출문제로 아웃풋하면서 모르는 부분을

 다시 이론에서 찾아서 공부하고, 부족한 개념은 챗OOO 에게 도움을 받으면 충분히 합격할 수 있으리라 봅니다. 




댓글(0) 먼댓글(0) 좋아요(0)
좋아요
l 공유하기 l 북마크하기찜하기 lthankstoThanksTo
 
 
 
김앤북 내일은 데이터분석 준전문가(ADsP)
Jade Jeong 지음 / 아이비김영(김앤북) / 2024년 7월
평점 :
장바구니담기


기출 중심 학습이라는 포인트가 눈에 띄는 ADSP 자격증 대비책이네요.

댓글(0) 먼댓글(0) 좋아요(0)
좋아요
l 공유하기 l 북마크하기찜하기 lthankstoThanksTo
 
 
 
2025 이기적 리눅스마스터 1급 (1·2차) - 최신 출제기준 반영 + CBT 온라인 문제집 + 구매인증 PDF ㅣ 2025 이기적 리눅스마스터
김윤수.최정현 지음 / 영진.com(영진닷컴) / 2024년 1월
평점 :
구판절판


자격증은 언제나 이기적 시리즈로 준비하면 든든합니다

댓글(0) 먼댓글(0) 좋아요(0)
좋아요
l 공유하기 l 북마크하기찜하기 lthankstoThanksTo
 
 
 
이기적 경영정보시각화능력 필기 기본서 - 최신판 + 신설 국가기술자격증 + CBT 온라인 문제집
인천대학교 비즈니스데이터센터.경기대 빅데이터 시각화 연구실.이베로니카 지음 / 영진.com(영진닷컴) / 2024년 3월
평점 :
구판절판


오랫동안 OLAP 시스템을 운영하면서 태블로 등의 자격증에 관심을 가지고 있었으나 해외 자격증이라 미루고 있었는데 국내 자격증이 생겨서 관심을 가지게 되었네요. 믿을만한 "이기적"시리즈에서 출간되어 기대됩니다

댓글(3) 먼댓글(0) 좋아요(0)
좋아요
l 공유하기 l 북마크하기찜하기 lthankstoThanksTo
 
 
데이터인사이트 2026-10-30 11:03   좋아요 0 | 댓글달기 | URL
import io
import os
import re
import sys
import textwrap
from contextlib import contextmanager, redirect_stdout
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
from typing import Optional

from pyspark.sql import SparkSession


# ==================== 실행 설정 ====================
VALIDATE_QUERY_FILES = [
˝.sql˝,
]

OUTPUT_FILE_NAME = ˝.txt˝ # 결과 저장 파일명
PREVIEW_ROWS = 40 # 결과 있는 쿼리의 미리보기 행 수
KST = timezone(timedelta(hours=9))

# 결과 출력 방식
# ˝immediate˝ : 쿼리 실행 직후 결과/오류를 바로 출력
# ˝deferred˝ : 전체 실행이 끝난 뒤 0건 -> 결과 있음 -> 오류 순서로 한꺼번에 출력
RESULT_OUTPUT_MODE = ˝immediate˝

IMMEDIATE = ˝immediate˝
DEFERRED = ˝deferred˝

# SQL 파일 내 ${변수명}에 치환될 값
SQL_VARIABLES = {
˝plant_no˝: ˝˝,
˝schema˝: ˝˝,
˝ldg_ymd˝: ˝2026-10-04˝,
˝DW_LDG_YMD˝: ˝9999-12-31˝,

˝LOAD_JOB_GUBUN˝: ˝‘‘˝, # 대체값: ˝table_cnt˝
˝LOAD_TGT_TAB˝: ˝‘‘˝,
˝LOAD_PLANT_NO˝: ˝--and = ‘0003‘˝,

˝LOAD_JOB_GUBUN2˝: ˝and = ‘table_cnt‘˝,
# 대체값: ˝and LOAD_SEQ in (‘4464‘,‘10139‘,‘10140‘)˝
˝LOAD_TGT_TAB2˝: ˝and LOAD_TGT_TAB = ‘‘˝,
˝LOAD_PLANT_NO2˝: ˝and LOAD_PLANT_NO = ‘‘˝,

˝WHERE˝: ˝WHERE 1=1˝, # 대체값: ˝WHERE tgt_cnt <> sum_by_src_col_val˝
}

# 실행 전에 REFRESH TABLE 할 대상
REFRESH_TABLES = [
˝a_dsp_mfr.˝,
˝a_dsp_mfr.˝,
˝a_dsp_mfr.˝,
˝a_dsp_mfr.˝,
]

# Spark 세션 설정
SPARK_CONF = {
˝spark.sql.extensions˝: ˝org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions˝,
˝spark.sql.catalog.spark_catalog˝: ˝org.apache.iceberg.spark.SparkSessionCatalog˝,
˝spark.sql.iceberg.handle-timestamp-without-timezone˝: ˝true˝,
˝spark.hadoop.mapreduce.input.fileinputformat.input.dir.recursive˝: ˝true˝,
˝spark.sql.autoBroadcastJoinThreshold˝: ˝-1˝,
˝spark.sql.adaptive.autoBroadcastJoinThreshold˝: ˝-1˝,
˝spark.sql.adaptive.enabled˝: ˝false˝,
˝spark.sql.shuffle.partitions˝: ˝800˝,
}


# ==================== 결과 자료구조 ====================
@dataclass
class QueryResult:
file: str
query_no: int
sql: str
sql_head: str # SQL 앞 3줄 (오류 헤더용)
row_count: int = 0
preview: str = ˝˝
error: Optional[str] = None

@property
def ok(self) -> bool:
return self.error is None


# ==================== 출력 유틸 (화면 + 파일 동시 출력) ====================
class TeeWriter:
˝˝˝write 호출을 원래 stdout과 파일에 동시에 기록한다.˝˝˝

def __init__(self, stream, file):
self.stream = stream
self.file = file

def write(self, data: str) -> int:
self.stream.write(data)
self.file.write(data)
self.file.flush() # 강제 종료되어도 출력이 남도록 매번 flush
return len(data)

def flush(self):
self.stream.flush()
self.file.flush()


@contextmanager
def tee_stdout(file_path: str):
˝˝˝with 블록 안의 print 출력을 화면과 파일에 함께 남기고, 종료 시 stdout을 복원한다.˝˝˝
with open(file_path, ˝w˝, encoding=˝utf-8˝) as f:
with redirect_stdout(TeeWriter(sys.stdout, f)):
yield


def print_banner(title: str, width: int = 180) -> None:
print(f˝n{‘=‘ * width}˝)
print(title)
print(f˝{‘=‘ * width}˝)


def print_sub_banner(title: str, width: int = 80) -> None:
print(f˝n{‘-‘ * width}˝)
print(title)
print(f˝{‘-‘ * width}˝)


def now_str() -> str:
return datetime.now(KST).strftime(˝%Y%m%d_%H%M%S˝)


# ==================== 문자열/SQL 유틸 ====================
def replace_sql_variables(sql_text: str, variables: dict) -> str:
˝˝˝
SQL 내부의 ${변수명}을 variables 값으로 치환한다.
정의되지 않은 변수가 있으면 ValueError를 발생시킨다.
˝˝˝
def _replace(match):
name = match.group(1)
if name not in variables:
available = ˝, ˝.join(variables.keys())
raise ValueError(
f˝정의되지 않은 SQL 변수: ‘${{{name}}}‘n사용 가능한 변수: {available}˝
)
return str(variables[name])

return re.sub(r˝${([a-zA-Z_][a-zA-Z0-9_]*)}˝, _replace, sql_text)


def remove_iceberg_prefix(sql_text: str) -> tuple:
˝˝˝
‘iceberg.‘ 접두어를 제거한다 (대소문자 무시).
예) FROM iceberg.a_dsp_mfr.DW_MODEL_B -> FROM a_dsp_mfr.DW_MODEL_B
Returns: (변환된 SQL, 제거 건수)
˝˝˝
pattern = re.compile(r˝(?<![A-Za-z0-9_])iceberg.˝, re.IGNORECASE)
return pattern.subn(˝˝, sql_text)


def split_statements(sql_text: str) -> list:
˝˝˝‘;‘ 기준으로 SQL 문장을 나누고 빈 문장은 제외한다.˝˝˝
return [s.strip() for s in sql_text.split(˝;˝) if s.strip()]


def first_lines(sql: str, n: int = 3) -> str:
˝˝˝SQL의 앞 n줄을 반환한다. 빈 줄은 제외하고 실제 내용이 있는 줄만 센다.˝˝˝
lines = [line.strip() for line in sql.splitlines() if line.strip()]
return ˝n˝.join(lines[:n])


def short_error(e: Exception, max_lines: int = 2) -> str:
˝˝˝오류 메시지의 앞 몇 줄만 사용한다.˝˝˝
lines = [line.strip() for line in str(e).splitlines() if line.strip()]
return ˝n˝.join(lines[:max_lines])


def validate_output_mode(mode: str) -> str:
if mode not in (IMMEDIATE, DEFERRED):
raise ValueError(
f˝RESULT_OUTPUT_MODE 값이 잘못됨: {mode!r} (허용: {IMMEDIATE!r}, {DEFERRED!r})˝
)
return mode

데이터인사이트 2026-10-30 11:00   좋아요 0 | 댓글달기 | URL

# ==================== Spark ====================
def build_spark() -> SparkSession:
˝˝˝Spark 세션을 만들고 설정을 적용한다.˝˝˝
builder = SparkSession.builder.appName(˝create integrate no˝)
for key, value in SPARK_CONF.items():
builder = builder.config(key, value)
spark = builder.getOrCreate()

spark.sparkContext._jsc.hadoopConfiguration().set(
˝mapreduce.input.fileinputformat.input.dir.recursive˝, ˝true˝
)
spark.sparkContext.setLogLevel(˝ERROR˝)
spark.catalog.clearCache()
return spark


def refresh_tables(spark: SparkSession) -> None:
˝˝˝설정된 테이블의 메타데이터를 갱신한다.˝˝˝
for table in REFRESH_TABLES:
spark.sql(f˝REFRESH TABLE {table}˝)


# ==================== SQL 파일 로드 ====================
def load_query_file(path: str) -> str:
˝˝˝
SQL 파일을 읽고 변수 치환과 iceberg. 제거를 적용한다.
파일 오류는 예외로 올라가며, 호출부에서 파일 단위 오류로 기록한다.
˝˝˝
with open(path, ˝r˝, encoding=˝utf-8˝) as f:
text = f.read()

text = replace_sql_variables(text, SQL_VARIABLES)
text, removed = remove_iceberg_prefix(text)
print(f˝[iceberg. 제거 건수] {removed}건˝)
return text


# ==================== 개별 결과 출력 ====================
def print_result_block(r: QueryResult) -> None:
˝˝˝성공한 쿼리 1건의 결과(SQL + 미리보기)를 출력한다.˝˝˝
print_sub_banner(f˝[{r.file}] 쿼리 {r.query_no} (결과 {r.row_count}행)˝)
#print(r.sql)
#print()
print(r.preview, end=˝˝)


def print_error_block(r: QueryResult) -> None:
˝˝˝실패한 쿼리 1건의 오류 내용과 SQL을 출력한다.˝˝˝
print_sub_banner(f˝[{r.file}] 쿼리 {r.query_no} 오류˝)
print(˝[SQL 앞 3줄]˝)
print(textwrap.indent(r.sql_head, ˝ ˝))
print(f˝[오류 내용] {r.error}˝)
print_sub_banner(f˝[{r.file}] 쿼리 {r.query_no} SQL˝)
print(r.sql)
print()


def print_query_outcome(r: QueryResult) -> None:
˝˝˝성공/실패에 따라 적절한 블록을 출력한다.˝˝˝
if r.ok:
print_result_block(r)
else:
print_error_block(r)


# ==================== 쿼리 실행 ====================
def run_statement(spark: SparkSession, file: str, query_no: int, sql: str,
show_now: bool) -> QueryResult:
˝˝˝
쿼리 1건을 실행하고 건수와 미리보기를 기록한다.
show_now가 True면 실행 직후 결과를 바로 출력한다.
오류가 나도 예외를 올리지 않고 다음 쿼리로 진행한다.
˝˝˝
result = QueryResult(file=file, query_no=query_no, sql=sql,
sql_head=first_lines(sql, 3))
print(f˝[실행 {query_no}] [SQL 전체]n{sql}˝)
#print(f˝[실행 {query_no}]˝)
try:
df = spark.sql(sql)
result.row_count = df.count()

if result.row_count > 0:
buf = io.StringIO()
with redirect_stdout(buf):
df.show(PREVIEW_ROWS, truncate=False, vertical=False)
result.preview = buf.getvalue()

print(f˝[성공 {query_no}] 데이터 {result.row_count}건˝)

except Exception as e:
result.error = short_error(e)
print(f˝[실패 {query_no}] {now_str()}˝)

if show_now:
print_query_outcome(result)

return result


def run_file(spark: SparkSession, file: str, file_idx: int, total: int,
mode: str) -> tuple:
˝˝˝
SQL 파일 1개를 실행한다.
Returns: (쿼리 결과 리스트, 파일 단위 오류 dict 또는 None)
˝˝˝
print_banner(f˝[조회 파일 {file_idx}/{total}] {file}˝)

try:
query_text = load_query_file(file)
except FileNotFoundError:
print(f˝❌ 파일을 찾을 수 없음: {file}˝)
return [], {˝file˝: file, ˝error˝: ˝File not found˝}
except ValueError as e:
print(f˝❌ SQL 변수 치환 실패: {file}˝)
return [], {˝file˝: file, ˝error˝: str(e)}

statements = split_statements(query_text)
show_now = (mode == IMMEDIATE)
results = [
run_statement(spark, file, no, sql, show_now)
for no, sql in enumerate(statements, start=1)
]

ok_count = sum(1 for r in results if r.ok)
print_sub_banner(f˝📌 파일 {file_idx} 결과 요약: {file}˝, width=80)
print(f˝전체 쿼리 수 : {len(statements)}˝)
print(f˝✅ 성공 수 : {ok_count}˝)
print(f˝❌ 실패 수 : {len(results) - ok_count}˝)

return results, None


# ==================== 최종 출력 ====================
def print_totals(all_results: list, file_count: int) -> None:
zero = [r for r in all_results if r.ok and r.row_count == 0]
nonzero = [r for r in all_results if r.ok and r.row_count > 0]
errors = [r for r in all_results if not r.ok]

print_banner(˝✅ 전체 조회 쿼리 처리 완료˝)
print(˝n📊 [조회 쿼리 최종 결과]˝)
print(f˝처리된 파일 수 : {file_count}˝)
print(f˝✅ 성공 쿼리 수 : {len(all_results) - len(errors)}˝)
print(f˝❌ 실패 쿼리 수 : {len(errors)}˝)
print(f˝📋 결과 0건 쿼리 수 : {len(zero)}˝)
print(f˝📋 결과 있는 쿼리 수 : {len(nonzero)}˝)


def print_deferred_results(all_results: list) -> None:
˝˝˝DEFERRED 모드: 0건 -> 결과 있음 -> 오류 순서로 한꺼번에 출력한다.˝˝˝
zero = [r for r in all_results if r.ok and r.row_count == 0]
nonzero = [r for r in all_results if r.ok and r.row_count > 0]
errors = [r for r in all_results if not r.ok]

print_banner(f˝📋 [결과 0건 쿼리 목록] : {len(zero)}건˝)
for r in zero:
print_result_block(r)

print_banner(f˝📋 [결과 있는 쿼리 상세] : {len(nonzero)}건˝)
for r in nonzero:
print_result_block(r)

print_banner(f˝❌ [쿼리 단위 오류 상세] : {len(errors)}건˝)
for r in errors:
print_error_block(r)


def print_immediate_notice(all_results: list) -> None:
˝˝˝IMMEDIATE 모드: 결과는 이미 출력되었으므로 분류 개수만 알려준다.˝˝˝
zero = sum(1 for r in all_results if r.ok and r.row_count == 0)
nonzero = sum(1 for r in all_results if r.ok and r.row_count > 0)
errors = sum(1 for r in all_results if not r.ok)

print_banner(˝📋 [결과 출력] 실행 중 즉시 출력 완료˝)
print(f˝- 결과 0건 : {zero}건˝)
print(f˝- 결과 있음 : {nonzero}건˝)
print(f˝- 오류 : {errors}건 (상세는 실행 중 출력됨)˝)


def print_error_summary(all_results: list, file_errors: list) -> None:
˝˝˝파일 단위 오류는 항상 출력한다. 쿼리 오류는 개수만 요약한다.˝˝˝
errors = [r for r in all_results if not r.ok]
print_banner(f˝❌ [오류 정리] : {len(file_errors) + len(errors)}건˝)

if file_errors:
print(f˝n[파일 단위 오류] : {len(file_errors)}건˝)
for fe in file_errors:
print(f˝- 파일: {fe[‘file‘]}˝)
print(f˝ 오류: {fe[‘error‘]}˝)

데이터인사이트 2026-10-30 11:00   좋아요 0 | 댓글달기 | URL

if errors:
print(f˝n[쿼리 단위 오류] : {len(errors)}건˝)
for r in errors:
print(f˝- [{r.file}] 쿼리 {r.query_no}: {r.error.splitlines()[0]}˝)


# ==================== 메인 ====================
def main() -> None:
mode = validate_output_mode(RESULT_OUTPUT_MODE)
spark = build_spark()

with tee_stdout(OUTPUT_FILE_NAME):
print(f˝✅ Work Dir: {os.getcwd()}˝)
print(f˝✅ Start Time: {now_str()}˝)
print(f˝✅ 결과 출력 방식: {mode}˝)

refresh_tables(spark)

print_banner(˝검증 쿼리 파일 반복 실행˝)

all_results = []
file_errors = []
for idx, file in enumerate(VALIDATE_QUERY_FILES, start=1):
results, file_error = run_file(spark, file, idx, len(VALIDATE_QUERY_FILES), mode)
all_results.extend(results)
if file_error:
file_errors.append(file_error)

print_totals(all_results, len(VALIDATE_QUERY_FILES))

if mode == DEFERRED:
print_deferred_results(all_results)
else:
print_immediate_notice(all_results)

print_error_summary(all_results, file_errors)

print(f˝n[전체종료] {now_str()}˝)
print(˝=˝ * 180)

print(f˝결과 파일 저장 완료: {OUTPUT_FILE_NAME}˝)


if __name__ == ˝__main__˝:
main()
 
처음 처음 | 이전 이전 | 1 | 2 | 3 | 4 |다음 다음 | 마지막 마지막