해결된 질문
작성
·
725
·
수정됨
0
private List<OrderSpecifier> getOrderSpecifier() {
List<OrderSpecifier> orderSpecifiers = new ArrayList<>();
//승인 안된 관리자 우선 조회
orderSpecifiers.add(new OrderSpecifier<>(Order.ASC, admin.isAuthorized));
orderSpecifiers.add(new OrderSpecifier(
new CaseBuilder()
.when(admin.isAuthorized.eq("FALSE")).then(admin.createdAt.asc())
.when(admin.isAuthorized.eq("TRUE")).then(admin.createdAt.desc())
));
return orderSpecifiers;
}
아래와 같은 order 순서로 정렬하려 하는데 2,3 조건을 나누는 부분이 잘 되지 않아 질문 남깁니다. CaseBuilder 대신 다른 방법이 있나요?
승인 받지 못한 관리자(isAuthorized = 'FALSE') 먼저 조회
isAuthorized = 'FALSE' 인 경우에는 createdAt asc
isAuthorized = 'TRUE' 인 경우에는 createdAt desc
답변 3
0
안녕하세요. olive3three님
우선 case 쿼리를 작성할 때 항상 else 조건을 생각해야 합니다.
현재 else 조건을 넣지 않았는데요. 이 경우 조건을 만족하지 않으면 숫자는 0, 나머지는 null이 됩니다.
참고로 Querydsl에서는 otherwise()를 넣어주어야 합니다.
2가지 정도 해결 방안을 말씀드릴게요.
먼저 적어주신 내용으로는 다음과 같이 쿼리를 작성하시면 됩니다.
List<Admin> result = queryFactory.selectFrom(admin)
.orderBy(new CaseBuilder()
.when(admin.isAuthorized.eq("FALSE")).then(0)
.when(admin.isAuthorized.eq("TRUE")).then(1)
.otherwise(2).asc(),
new CaseBuilder()
.when(admin.isAuthorized.eq("FALSE")).then(admin.createdAt)
.otherwise(LocalDateTime.now()).asc(),
new CaseBuilder()
.when(admin.isAuthorized.eq("TRUE")).then(admin.createdAt)
.otherwise(LocalDateTime.now()).desc()
)
.fetch();
다음과 같이 날짜 자체를 숫자로 변경한 다음, 숫자로 변경한 날짜를 정렬 조건으로 사용해 한번에 처리하는 방식으로 문제를 해결할 수도 있습니다.
// 날짜를 문자로 변경한 다음에 문자를 양수로 변경
StringTemplate formattedDateAsc = Expressions.stringTemplate(
"CAST(FORMATDATETIME({0}, {1}) AS LONG)"
, admin.createdAt
, ConstantImpl.create("yyyyMMddHHmmss")); // 양수
// 날짜를 문자로 변경한 다음에 문자를 음수로 변경
StringTemplate formattedDateDesc = Expressions.stringTemplate(
"CAST(FORMATDATETIME({0}, {1}) AS LONG)"
, admin.createdAt
, ConstantImpl.create("-yyyyMMddHHmmss")); // 음수
List<Admin> result = queryFactory.selectFrom(admin)
.orderBy(new CaseBuilder()
.when(admin.isAuthorized.eq("FALSE")).then(formattedDateDesc)
.when(admin.isAuthorized.eq("TRUE")).then(formattedDateAsc)
.otherwise(formattedDateAsc).asc())
.fetch();
감사합니다.
IS_AUTHORIZED = 'FALSE'인 경우에는 CREATED_AT이 내림차순으로 IS_AUTHORIZED = 'TRUE'인 경우에는 CREATED_AT이 오름차순으로 정렬되었으면 합니다.
안녕하세요. olive3three님
정확히 어떤 문제인지 저희가 이해하기 위해서 추가 정보가 필요합니다. 먼저 기대하는 내용이 SQL에서 작동하는지 확인이 필요합니다.
다음 내용을 자세히 남겨주세요 🙂
테이블 DDL
예제 insert DML
생각하시는 조회 SQL
SQL 실행의 조회 결과
감사합니다.
Admin 테이블 DDLDROP TABLE IF EXISTS ADMIN CASCADE;
CREATE TABLE ADMIN
(
ADMIN_ID BIGINT UNSIGNED GENERATED BY DEFAULT AS IDENTITY,
LOGIN_ID VARCHAR(20) NOT NULL,
PASSWORD VARCHAR(100) NOT NULL,
NAME VARCHAR(5) NOT NULL,
EMAIL VARCHAR(45) NOT NULL,
IS_AUTHORIZED VARCHAR(10) NOT NULL,
AUTHORITY VARCHAR(15) NOT NULL,
CREATED_AT TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
MODIFIED_AT TIMESTAMP,
PRIMARY KEY (ADMIN_ID),
UNIQUE KEY ADMIN_LOGIN_ID_UNIQUE (LOGIN_ID),
UNIQUE KEY ADMIN_EMAIL_UNIQUE (EMAIL)
);
예제 insert DML
INSERT INTO TEST VALUES(1, 'admin1', 'admin1234!', '관리자1', 'admin1@gmail.com', 'TRUE', 'ROLE_ADMIN', '2024-07-11 14:30:00', '2024-07-11 14:30:00');
INSERT INTO TEST VALUES(2, 'admin2', 'admin1234!', '관리자2', 'admin2@gmail.com', 'TRUE', 'ROLE_ADMIN', '2024-07-12 14:30:00', '2024-07-12 14:30:00');
INSERT INTO TEST VALUES(3, 'admin3', 'admin1234!', '관리자3', 'admin3@gmail.com', 'FALSE', 'ROLE_ANONYMOUS', '2024-07-13 14:30:00', '2024-07-13 14:30:00');
INSERT INTO TEST VALUES(4, 'admin4', 'admin1234!', '관리자4', 'admin4@gmail.com', 'FALSE', 'ROLE_ANONYMOUS', '2024-07-14 14:30:00', '2024-07-14 14:30:00');
조회 SQL
SELECT * FROM TEST
ORDER BY
CASE
WHEN is_authorized = 'FALSE' THEN 0
WHEN is_authorized = 'TRUE' THEN 1
END,
CASE
WHEN is_authorized = 'FALSE' THEN created_at
END ASC,
CASE
WHEN is_authorized = 'TRUE' THEN created_at
END DESC;
SQL 실행의 조회 결과
3번의 SQL문을 QueryDsl로 바꾸고 싶습니다. 또한 SQL문이 올바르게 짠건지 궁금합니다.
0
안녕하세요, 인프런 AI 인턴입니다. olive3three님의 질문과 관련해, 주어진 조건에 따라 특정 엔티티의 리스트를 정렬하는 방법에 대해 질문하셨군요. 여러분이 질문하신 OrderSpecifier
를 사용하여 isAuthorized
의 값에 따라 다른 정렬 순서를 적용하는 방법에 대해 말씀드리겠습니다.
질문하신 내용과 유사한 상황에 대해 처리하는 방법을 설명한 기존 답변은 아래 링크에서 찾을 수 있습니다:
CaseBuilder
를 사용하는 방법을 설명하고 있습니다. 여러분의 경우에도 CaseBuilder
를 이용하여 isAuthorized
값에 따라 다른 정렬 기준을 적용하는 것이 가능합니다. 이 방법은 여러분이 사용하고자 하는 조건 분기에 맞게 조금만 변형하면 적용할 수 있을 것으로 보입니다.위의 답변에서 CaseBuilder
를 사용하여 조건에 따라 다른 OrderSpecifier
를 생성하는 방식을 다루고 있으며, 이 방법은 여러분이 시도하고자 하는 조건 분기에 맞게 적응할 수 있습니다. 주어진 코드 예제에서는 enum 값을 기준으로 정렬 순서를 정의하는 예를 다루었으나, 해당 방식을 isAuthorized
값에 기반하여 수정하는 것도 가능합니다. 예를 들면, isAuthorized
값에 따라 다른 createdAt
정렬 순서를 적용하려면, 여러분의 CaseBuilder
로직을 유지하면서, 적절한 반환 타입을 활용해야 합니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
답변 감사합니다!!