본문 바로가기

개발자정보

세일즈포스 관리자를 위한 SOQL :: Create SOQL Queries to get data from your Salesforce org.

반응형

SOQL 쿼리 시작하기

학습 목표

이 단원을 완료하면 다음을 수행할 수 있습니다.

  • 필수 절을 사용하여 유효한 SOQL 쿼리를 구성합니다.
  • 여러 조건으로 쿼리 결과를 필터링합니다.
  • 쿼리 결과를 정렬합니다.

Build Apex Coding Skills 트레일 의 첫 번째 정류장이라면 너무 멀리 온 것입니다. 스텝 등을 타고 벌 관리자에 대한 에이펙스 기본 사항  관리자를위한 객체 지향 프로그래밍 이 모듈 계속하기 전에 배지.

이미 해당 배지를 획득했습니까? 잘했습니다! 이제 클래스, 변수 및 sObject를 만드는 방법에 대해 기본적으로 이해했으므로 SOQL(sockle로 발음됨)이라고도 하는 Salesforce 개체 쿼리 언어에 대해 알아볼 차례입니다.

SOQL이란 무엇입니까?

SOQL은 Salesforce 데이터베이스에서 레코드 데이터를 가져오는 언어입니다. 에서 관리자를위한 객체 지향 프로그래밍 당신은 당신이, 업데이트 및 삭제 레코드를 삽입하는 데이터 조작 언어 (DML) 문을 사용할 수 있다는 것을 배웠습니다. 그러나 데이터베이스에 이미 존재하는 데이터를 얻으려면 어떻게 해야 할까요? SOQL을 사용하면 데이터를 쉽게 검색할 수 있습니다. 

SOQL 쿼리를 만드는 것은 보고서를 만드는 것과 비슷합니다. 보고서를 작성할 때 다음과 같은 질문에 답합니다.

  1. 어떤 필드를 표시하고 싶습니까?
  2. 해당 필드는 어디에 있습니까?

SOQL 쿼리를 생성할 때도 동일한 질문을 합니다. 쿼리에서 이러한 질문에 대한 답변은 필드와 개체입니다. 

이 쿼리에는 SOQL 키워드( SELECT및 FROM), 레코드 필드( Name및 Email) 및 개체(표준 Contact개체)가 포함됩니다. 

이 쿼리는 무엇을 하고 있습니까? 데이터베이스의 연락처 레코드에 대한 특정 정보를 검색(가져오기)하는 것입니다. 이 조각들이 어떻게 서로 맞는지 살펴보고 몇 가지 쿼리 작성을 연습해 보겠습니다. 먼저 SOQL 쿼리의 필수 부분을 살펴봅니다.

필수 SOQL 조항

선택하다  

모든 SOQL 쿼리의 기초에는 SELECT 절과 FROM 절의 두 절이 있습니다. 절을 퍼즐 조각으로 생각하십시오. 전체 쿼리의 일부입니다.

모든 SOQL 쿼리에는 SELECT키워드로 시작하는 SELECT 절이 있습니다. SELECT 절은 Salesforce 레코드에서 하나 이상의 필드(쉼표로 구분)를 지정합니다. 이 예제 쿼리는 Name및 2개의 필드를 반환합니다 Email. 

필드 이름에 대한 참고 사항:  관리자는 다른 관리자와 대화할 때 필드 레이블로 필드를 참조할 수 있습니다. 그러나 코드에서 개발자는 대신 API 이름을 사용합니다. 따라서 SOQL 쿼리에서는 항상 필드 레이블이 아닌 필드 API 이름을 사용하십시오. 필드의 API 이름이 무엇인지 확실하지 않더라도 걱정하지 마세요. 알아낼 수 있는 방법이 있습니다. 이 모듈의 뒷부분에서 자세히 설명합니다.

에서

SOQL 쿼리를 만드는 데 필요한 두 번째 절은 FROM 절입니다. 

FROM키워드로 시작 하여 FROM 절은 Salesforce 데이터베이스의 개체를 지정합니다. 이 경우 Contact객체의 데이터가 필요 합니다. 쿼리를 실행할 때 데이터가 어떻게 보이는지 봅시다. 

함께 따라와 함께 트레일

이 단계를 진행하면서 강사와 함께 하고 싶으십니까? Trailhead Live에서 Trail Together 시리즈의 일부인 이 비디오를 보십시오. 리소스 섹션에서 전체 세션에 대한 링크를 찾을 수 있습니다. 

 

SOQL을 직접 체험할 준비가 되셨습니까?

이 단원에서는 개발자 콘솔의 쿼리 편집기에서 SOQL 쿼리를 작성하는 단계를 보여줍니다. 이 단원에는 실습 과제가 없지만, 단계를 따르고 시도하려면 지금 새로운 Trailhead Playground를 만드십시오. 방법을 알아 보려면 Trailhead Playground Management 모듈을 참조하십시오 . Salesforce에서 Trailhead Playground를 만드는 데 일반적으로 3-4분이 걸립니다. 또한 이 모듈의 뒷부분에서 실습 과제를 완료할 때 플레이그라운드를 사용합니다.

예, 우리는 정말로 새로운 Trailhead 놀이터를 의미합니다! 기존 조직이나 놀이터를 사용하는 경우 도전 과제를 완료하는 데 문제가 발생할 수 있습니다.

쿼리 편집기를 사용하여 쿼리 작성

  1. Trailhead Playground에서 을 클릭 
    한 다음 개발자 콘솔 을 선택 합니다.
  2. 클릭 파일 | 열기 | 개체 | 연락처 .
  3. 열기 를 클릭 합니다.
    연락처 개체가 열리고 관련된 모든 필드의 이름과 유형이 나열됩니다.
  4. 하단 패널에서 쿼리 편집기 탭을 선택합니다 . (탭이 표시되지 않으면 창 아래쪽에 있는 위쪽 화살표를 클릭합니다.) 

    쿼리 편집기에는 세 개의 섹션이 있습니다. 왼쪽 상단 섹션(1)에 쿼리가 표시됩니다. 거기에서 쿼리를 편집할 수 있습니다. 왼쪽 하단 섹션(2)에 오류가 표시됩니다. 그리고 오른쪽 섹션(3)은 실행된 SOQL 쿼리의 이력을 저장합니다.
  5. CTRL 키를 누른 상태에서 클릭(Windows) 또는 CMD 키를 누른 상태에서 클릭(Mac)하여 이메일 , 이름  언어__c 필드를 선택 합니다.
  6. 쿼리 를 클릭 합니다.
    선택한 개체 및 필드를 기반으로 하는 SOQL 쿼리가 쿼리 편집기에 표시됩니다. 쿼리 빌더에서 필드를 선택하면 쿼리 빌더가 필드 API 이름을 SOQL 쿼리에 자동으로 삽입합니다. 이 도구를 사용하면 API 이름을 외우거나 검색할 필요가 없습니다.
  7. 실행 을 클릭 합니다 .

쿼리가 실행된 후 결과에 요청된 내용이 정확히 표시됩니다. 또한 쿼리 편집기를 사용하면 ID가 보너스로 반환됩니다. 정말 멋진!

선택적 SOQL 조항

SELECT 절과 FROM 절은 필수이지만 SOQL에는 쿼리를 구체화하는 선택적 절도 있습니다. 

Trailhead Playground에서 생성한 예제 쿼리는 상당히 적은 수의 레코드를 반환합니다. 마지막 쿼리는 20개의 레코드를 반환했습니다. 그러나 수천 개의 레코드가 있다면 어떻게 될까요? 해당 데이터를 처리하는 데 필요한 컴퓨팅 성능의 양은 상당할 것입니다. SOQL에 모든 레코드의 하위 집합을 반환하는 방법이 있다면 좋지 않을까요? 사실, 그렇습니다.

어디  

WHERE 절은 레코드가 선택되고 반환되기 위해 일치해야 하는 조건을 설정합니다. 필터를 사용하여 목록 보기 또는 보고서에 표시되는 데이터를 제한하는 것과 동일한 방식으로 WHERE 절을 사용합니다. 예를 들어 이름이 Stella인 연락처를 찾는 경우 WHERE FirstName = 'Stella'쿼리 끝에 다음과 같이 추가할 수 있습니다 .

SELECT Name, Email FROM Contact WHERE FirstName = 'Stella'

복사

둘 이상의 조건을 사용하여 필터링하도록 WHERE 절을 정의할 수도 있습니다. AND, OR 및 IN의 세 가지 연산자를 사용하여 이를 수행하는 여러 가지 방법이 있습니다. 몇 가지 예를 살펴보겠습니다.

AND AND를 사용하여 두 가지 조건을 충족하는 레코드를 반환합니다. 이 쿼리는 이름이 Stella이고 성이 Pavlova인 모든 레코드를 반환합니다.

SELECT Name, Email
FROM Contact
WHERE FirstName = 'Stella' AND LastName = 'Pavlova'

OR OR을 사용하여 두 조건 중 하나를 충족하는 레코드를 반환합니다. 이 쿼리는 성이 James 또는 성이 Barr인 레코드를 반환합니다.


SELECT Name, Email
FROM Contact
WHERE LastName = 'James' OR LastName = 'Barr'

IN IN을 사용하여 세 개 이상의 조건 ​​중 하나 이상을 충족하는 레코드를 반환합니다. IN 절은 일반적으로 선택 목록의 값이나 LIST 또는 SET의 값을 반환하는 데 사용됩니다. IN은 그렇지 않으면 많은 OR 조건을 가질 수 있는 쿼리를 단순화합니다. 이 쿼리는 성이 James, Barr, Nedaark 또는 Forbes인 모든 레코드를 반환합니다.

SELECT Name, Email FROM Contact
WHERE LastName IN ('James', 'Barr', 'Nedaerk', 'Forbes')

LIMIT

LIMIT키워드 세트는 최대 레코드 수는 돌아갑니다. LIMIT는 테스트 중이고 쿼리가 대규모 데이터 집합을 처리할 때까지 기다리고 싶지 않을 때 유용합니다. SOQL에 대해 더 많이 배우면 너무 많은 레코드를 반환하지 않는 보다 적절한 방법을 발견하게 되지만 그때까지는 LIMIT가 쉬운 솔루션입니다. 쿼리에 제한을 추가해 보겠습니다. 

  1. 개발자 콘솔의 쿼리 편집기로 돌아갑니다.
  2. 쿼리 끝에 를 입력 LIMIT 5하여 다음과 같이 읽힙니다.
  3. SELECT Email, Name FROM Contact LIMIT 5
  4. 실행 을 클릭 합니다 .

쿼리 결과 창에는 5개의 결과가 표시됩니다. 

주문

이제 결과의 양을 처리했으므로 해당 결과를 어떻게 구성할 수 있습니까?  ORDER BY절을 사용하여 특정 필드의 값을 기준으로 결과를 정렬합니다. 선택적으로 ORDER BY 절에 한정자를 사용하여 스프레드시트에서와 같이 오름차순(기본값) 또는 내림차순을 지정합니다. 마지막으로 빈 필드 값이 많은 경우 NULLS 한정자를 사용하여 모든 NULL 값을 처음(기본값) 또는 마지막으로 그룹화합니다.

 

통사론 설명 예시
ASC 결과를 오름차순으로 반환 SELECT Name, Email FROM Contact
ORDER BY Name ASC
LIMIT 5

DESC 결과를 내림차순으로 반환
SELECT Name, Email FROM Contact
ORDER BY Email DESC
LIMIT 5

NULLS
FIRST | LAST
Returns null records at the beginning (NULLS FIRST) or end (NULLS LAST) SELECT Name, Email FROM Contact
ORDER BY Email
NULLS LAST

ASC 예 에서 5개의 연락처에서  필드를 이름에 따라 오름차순으로 정렬하여 SELECTName, Email FROM Contact ORDER BY Name ASC LIMIT 5반환합니다 .NameEmail

NULLS 예 SELECT Name, Email FROM Contact ORDER BY Email NULLS LAST 에서 이름과 이메일을 이메일로 오름차순으로 반환합니다(오름차순이 기본 정렬 순서이기 때문에). 이메일 주소가 없는 레코드는 끝에 그룹화됩니다.

SOQL의 강력한 기능에 대한 이 소개를 통해 이제 방대한 데이터 세트를 검색하고, 매우 구체적인 결과를 얻기 위해 제한을 설정하고, 필요에 맞게 반환된 데이터를 구성할 수 있습니다. 꽤 달콤한. 

 

Quiz

1. Which two clauses are required in a SOQL query?

A.SELECT and WHERE

B.FROM and LIMIT

C.SELECT and FROM

D.FROM and AND

 

2. Which query returns results for a specific account name?

A.SELECT ID, Name FROM Account WHERE ID = '0011000002c0h0i0AC'

B.SELECT ID, Name FROM Account WHERE Name = 'ACME Inc'

C.SELECT ID, Name FROM Account LIMIT 1

D.SELECT ID, Name FROM Contact WHERE Name = 'Rebecca Flores'

 

 

 

Apex 클래스에서 SOQL 쿼리 만들기

학습 목표

이 단원을 완료하면 다음을 수행할 수 있습니다.

  • 메서드에서 SOQL 쿼리를 만듭니다.
  • SOQL 쿼리에서 반환된 데이터를 조작합니다.

함께 따라와 함께 트레일

이 단계를 진행하면서 강사와 함께 하고 싶으십니까? Trailhead Live에서 Trail Together 시리즈의 일부인 이 비디오를 보십시오. 

 

(이 클립은 17분 32초부터 시작되며, 되감기하여 단계의 시작 부분을 다시 보고 싶은 경우를 대비해 보세요.)

소개

이제 SOQL 쿼리의 기본 사항을 이해했으므로 수식 필드에 대한 지식을 SOQL 쿼리에 적용할 수 있습니다.

쿼리는 매우 간단합니다.  SELECT FirstName, LastName FROM Contact

이제 결과 데이터를 저장할 개체가 필요합니다. SOQL 쿼리는 항상 목록 형식으로 데이터를 반환하므로 Apex 목록을 만듭니다. 관리자를 위한 Apex 기본 사항 에서 배운 것처럼 목록을 선언하려면 List예약어, 데이터 유형( < >문자) 및 새 목록의 이름과 같은 몇 가지 사항이 필요 합니다. 이 쿼리의 데이터 유형은 연락처이고 새 목록의 이름을 listOfContacts로 지정합니다. 목록 선언은 다음과 같습니다.

List<Contact> listofContacts

쿼리 결과를 새 목록에 할당하기 위해 다음과 같이 할당 연산자인 등호 기호( = )를 목록 선언과 쿼리 사이에 넣습니다.

List<Contact> listofContacts = [SELECT FirstName, LastName FROM Contact];

구문을 확인하십시오. 쿼리는 대괄호로 묶이고 [  ]명령문은 세미콜론( ;)으로 끝납니다 .

개발자 콘솔에서 사용해 보겠습니다. 테스트 목적으로 연락처 목록을 디버그 로그로 보내 코드가 어떻게 작동하는지 확인할 수 있습니다.

개발자 콘솔에서 코드 테스트

  1. 개발자 콘솔에서 디버그 | 익명 실행 창을 엽니다 .
  2. 익명 실행 창에서 쿼리 결과를 새 목록에 할당합니다.List<Contact> listOfContacts = [SELECT FirstName, LastName FROM Contact LIMIT 2];복사
  3. 다음 줄에서 listOfContacts 목록을 디버그 로그로 보냅니다.
  4. system.debug(listOfContacts);복사
  5. 로그 열기 확인란을 클릭합니다 .
  6. 실행 을 클릭 합니다 .
  7. 실행 로그 창 하단에서 디버그 전용 확인란을 클릭합니다 .
    디버그 로그의 처음 두 항목은 다음과 같아야 합니다.
  8. [2]|DEBUG|()
  9. 쿼리가 결과를 찾지 못하면 여전히 목록을 반환하지만 목록은 비어 있습니다.

여기에서 실제로 무슨 일이 일어나고 있습니까?

코드가 실행되면 먼저 쿼리를 처리합니다.

SELECT FirstName, LastName FROM Contact LIMIT 2

복사

쿼리는 모든 연락처를 찾고 각 레코드에서 이름과 성을 가져옵니다. 그런 다음 코드는 해당 연락처 레코드에서 선택한 데이터를 listOfContacts라는 목록에 추가합니다.  

마지막으로 2행에 System.debug의 내용이 표시됩니다 listOfContacts. 

Apex에서 SOQL 쿼리 실행

이전 단원에서는 쿼리 편집기를 사용하여 테이블에 데이터를 반환했습니다. 이 단원에서는 익명 실행 창을 사용하여 쿼리를 실행하고 결과를 디버그 로그로 보냅니다. 지금으로서는 훌륭하지만 사용자가 개발자 콘솔에서 쿼리를 실행하지 않을 것입니다. 조직의 사용자 인터페이스에서 데이터를 반환하는 방법이 필요합니다. Apex 클래스와 메서드는 이를 수행하는 방법입니다. SOQL 쿼리를 실행하고 Apex에서 결과를 조작하는 방법을 살펴보겠습니다.

Apex 클래스에서 Apex 메서드를 만드는 것으로 시작합니다. Apex 메서드는 쿼리를 실행하여 원하는 데이터를 선택합니다.

  1. 개발자 콘솔에서 파일 | 새로운 | 에이펙스 클래스 .
  2. 클래스 이름을 ContactUtility클릭 확인 .
  3. 클래스가 열리고 클래스를 선언하는 코드가 표시되고 클래스 본문을 위한 공간이 남습니다.
  4. 2행에 라는 메서드를 추가합니다 viewContacts.
  5. public static void viewContacts(){ }복사
  6. 3행의 viewContacts메서드 내부에 쿼리를 실행하고 결과를 새 목록에 할당하는 코드를 붙여넣습니다.
  7. List<Contact> listOfContacts = [SELECT FirstName, LastName FROM Contact];복사
  8. 수업을 저장합니다.

이제 listOfContacts목록에 원하는 데이터가 있습니다. for 루프를 사용하여 목록을 반복하고 출력에 대해 원하는 형식을 구성합니다.

For 루프를 사용하여 목록 반복하기

에서 관리자를위한 객체 지향 프로그래밍 , 당신은 루프를 사용하여, 하나 하나, 목록에서 항목을 처리하는 방법을 배웠습니다. 여기에서 for 루프를 사용하여 각 연락처의 이름과 성을 결합하여 연락처의 전체 이름을 구성합니다. 먼저 루프를 만든 다음 루프 내의 각 레코드를 처리합니다.

for 루프를 선언하려면 변수 이름, 데이터 유형 및 루프가 반복되는 목록의 이름이 필요합니다.

for 루프에서는 특정 객체를 직접 참조하지 않습니다. 대신 루프 내에서 한 번에 하나씩 목록 항목을 나타내는 변수를 만듭니다. 변수는 목록의 각 항목에 대한 자리 표시자 역할을 합니다. 아무 이름이나 선택할 수 있지만 간단하게 유지하겠습니다. 우리는 사용할 것 con입니다. 그런 다음 변수의 데이터 유형인 Contact와 목록의 이름인 listOfContacts가 필요합니다. 모두 함께 보면 다음과 같습니다.

For 루프 선언

  1. viewContacts 메서드에서 SOQL 쿼리 뒤에 다음 코드를 붙여넣습니다.
  2. for (Contact con : listOfContacts){ //loop body }복사
  3. 수업을 저장합니다.

데이터베이스를 쿼리하고(1), 데이터를 선택하고, 목록에 데이터를 저장하고(2), for 루프를 생성했습니다(3).

다음으로 루프 내에서 목록의 항목을 처리합니다. 궁극적으로 각 연락처 listOfContacts를 다음 형식으로 표시하려고 합니다.

First Name: <contact’s first name>, Last Name: <contact’s last name>

목록의 항목에 대한 필드를 참조하려면 점 표기법을 사용하여 개체와 해당 필드(object.field)를 지정합니다. 예를 들어, 다음과 같이 con(객체 변수)과 FirstName(필드) 사이에 마침표(점 표기법의 "점")를 넣어 listOfContacts 목록에 있는 Contact 객체의 FirstName 필드를 참조하십시오. 

con.FirstName 

목록에는 별도의 성과 이름 필드가 있습니다. Apex에서는 연결을 사용하여 필드 값(때로는 리터럴 텍스트도 포함)을 결합합니다. ( Apex Basics for Admins 에서 연결 작업을 수행했습니다 .) 

새로 고침으로써 연결할 때 필드 데이터는 로 표시됩니다 object.field. 리터럴 텍스트는 작은따옴표로 묶습니다. 필요한 경우 리터럴 텍스트의 시작과 끝에 공백을 포함하는 것을 잊지 마십시오. 더하기 기호( + )를 사용하여 필드를 결합하거나 필드와 일부 리터럴 텍스트를 결합합니다.

for 루프의 본문을 채워봅시다. 먼저 listOfContacts 목록의 모든 항목에 대해 Fullname이라는 새 변수에 FirstName과 LastName을 결합합니다.

String fullName = 'First Name: ' + con.FirstName + ', Last Name: ' + con.LastName;

복사

FirstName과 LastName 사이의 공백을 확인하십시오. 출력은 다음과 같아야 합니다.

First Name: Angela, Last Name: Carter 

~ 아니다 

FirstName:Angela,LastName:Carter

fullName 변수(데이터 유형: 문자열)에 대한 값이 할당된 후 해당 변수를 다음 줄의 디버그 문에 연결합니다. 

system.debug(fullName); 

For 루프의 프로세스 목록 항목

  1. viewContacts 메서드에서 //loop body다음 코드로 바꿉니다 .
  2. String fullName = 'First Name: ' + con.FirstName + ', Last Name: ' + con.LastName;
    system.debug(fullName);
  3. 수업을 저장합니다.

코드는 다음과 같아야 합니다.

public class ContactUtility {
    public static void viewContacts(){
        List<Contact> listOfContacts = [SELECT FirstName, LastName FROM Contact];
        for (Contact con : listOfContacts){
            String fullName = 'First Name: ' + con.FirstName + ', Last Name: ' + con.LastName;
            system.debug(fullName);
        }
    }
}

 

이제 클래스, 메서드 및 SOQL 쿼리가 준비되었으므로 코드를 실행하고 작동하는지 확인하겠습니다. 익명 실행 창에서 Apex 코드를 실행하려면 점 표기법을 사용하여 클래스와 메서드를 지정합니다.

  1. 익명 실행 창을 엽니다.
  2. Apex 코드 입력 창에서 기존 코드를 다음 코드로 바꿉니다.
  3. ContactUtility.viewContacts();
  4. 로그 열기 가 선택 되어 있는지 확인합니다 .
  5. 실행 을 클릭 합니다 .
  6. 디버그 전용 을 선택 합니다 .

결과의 처음 6개 행은 다음과 같아야 합니다.

실행 로그
이벤트 세부
USER_DEBUG [5]|DEBUG|First Name: Rose, Last Name: Gonzalez
USER_DEBUG [5]|DEBUG|First Name: Sean, Last Name: Forbes
USER_DEBUG [5]|DEBUG|First Name: Jack, Last Name: Rogers
USER_DEBUG [5]|DEBUG|First Name: Pat, Last Name: Stumuller
USER_DEBUG [5]|DEBUG|First Name: Andy, Last Name: Young
USER_DEBUG [5]|DEBUG|First Name: Tim, Last Name: Barr

저것 봐! SOQL, for 루프 및 연결을 사용하여 연락처 데이터를 검색하고 데이터를 목록에 할당하고 목록을 반복하고 예상 결과를 생성했습니다. 

 

Create a for loop to iterate through a SOQL query

Write a query to get the name and annual revenue of all accounts. Then use a for loop to iterate through each account, printing the name and annual revenue of each account to the debug log.

  • Create a class
    • Name: AccountUtility
  • Create a method
    • Name: viewAnnualRevenue
    • Keywords: public, static, and void
  • Create a list
    • Name: accountsList
  • Create a query and assign the results to a list
    • Fields: Account Name and Annual Revenue (Hint: Use API names, not field names or labels)
    • Object: Account
  • Create a for loop that iterates through the query results
    • Object: Account
    • List name: accountsList
    • For each item, concatenate the account name, followed by a colon, followed by the account’s annual revenue: <Account Name> : <Annual Revenue>
    • Store the concatenated string in a variable named acctRev
    • Print the acctRev variable to the debug log
public class AccountUtility {
    public static void viewAnnualRevenue(){
        // List<Account> accountsList = new List<Account>();
List<Account> accountsList = [SELECT Name, AnnualRevenue FROM Account];
        
        for (Account con : accountsList){
            String acctRev = 'revenue: ' + con.Name + ':' + con.AnnualRevenue;
            system.debug(acctRev);
        }
    }
}

 

표준 개체를 사용하여 관계 쿼리 만들기

학습 목표

이 단원을 완료하면 다음을 수행할 수 있습니다.

  • 두 가지 유형의 관계 쿼리를 설명합니다.
  • 두 개체 간의 관계를 식별합니다.
  • 점 표기법을 사용하여 자식에서 부모로 쿼리를 만듭니다.
  • 하위 쿼리를 사용하여 상위-하위 쿼리를 만듭니다.
  • 하위 쿼리를 사용하여 쿼리 결과를 필터링합니다.

함께 따라와 함께 트레일

이 단계를 진행하면서 강사와 함께 하고 싶으십니까? Trailhead Live에서 Trail Together 시리즈의 일부인 이 비디오를 보십시오. 

 

(이 클립은 36분 18초부터 시작되며, 되감기하여 단계의 시작 부분을 다시 보고 싶은 경우를 대비하여).

관계 쿼리 정보

Salesforce 관리자는 이미 관련 레코드에서 데이터를 가져오는 수식 필드에 익숙합니다. 이제 객체 관계에 대한 지식을 SOQL 쿼리 작성에 적용할 수 있습니다. 

FROM 절은 하나의 개체로 제한되지만 관계 쿼리를 사용하여 두 개의 관련 개체에 액세스할 수 있습니다. 관계 쿼리는 두 개체의 필드를 반환하기 위해 두 개체 간의 관계에 의존합니다. 개체 간 쿼리로 생각하십시오.

다음 요구 사항을 고려하십시오. 

"각 연락처의 계정 이름이 있는 모든 연락처 목록을 가져옵니다."

연락처 개체를 쿼리할 수 있지만 계정 이름 필드가 없습니다. 계정 이름은 실제로 연락처와 관련된 계정의 이름 필드입니다. org에서, 당신은에 필드에 액세스 할 수식 필드를 사용하여 모든 관련 객체입니다. Apex에서는 관계 쿼리를 사용하지만 관계 쿼리 유형 은 두 개체가 어떻게 관련되어 있는지에 따라 다릅니다. 

다음에 대한 기록을 얻으려면:

  • 하위 개체 및 관련 상위 개체의 필드를 포함하려면 하위 대 상위 쿼리를 사용합니다.
  • 상위 개체 및 관련 하위 개체의 필드를 포함하려면 상위-하위 쿼리를 사용합니다.

사용할 쿼리 유형을 결정하기 전에 두 개체인 연락처와 계정이 어떻게 관련되어 있는지 알아야 합니다. 어느 것이 부모이고 어느 것이 자식입니까?

개체의 관계 식별

관리자는 조직의 마스터-디테일 관계에 익숙합니다. 마스터-디테일 관계는 상위-하위 관계입니다. 마스터 개체는 상위 개체이고 세부 개체는 하위 개체입니다. 쿼리에 포함하려는 두 개체에 마스터-디테일 관계가 있는 경우 어느 것이 부모이고 어느 것이 자식인지 알 수 있습니다.

 

마스터-디테일 관계는 일대다 관계입니다. 마스터 개체(상위)에는 많은 세부 개체(하위)가 있을 수 있지만 각 세부 개체(하위)에는 하나의 마스터 개체(상위)만 있습니다.

쿼리에 포함하려는 두 개체에 익숙하지 않거나 관련 방법을 모르는 경우 개체 관리자에서 개체를 탐색합니다. 아이일 가능성이 더 큰 개체부터 시작하여 필드 및 관계를 살펴봅니다. 상위 개체에 연결할 수 있는 필드 이름을 찾습니다.

예를 들어 연락처에는 데이터 유형이 조회(계정)인 AccountId 필드가 있습니다. 코드 에서 필드 레이블 (계정 이름)이 아니라 필드 이름 (AccountId)이 필요하다는 것을 기억하십시오 

AccountId 필드에 대한 세부 정보에서 하위 관계 이름은 연락처(복수)입니다. 기본적으로 표준 개체의 관계 이름 은 자식 개체 이름  복수형 입니다.

하위 관계 이름은 연락처가 계정의 하위임을 확인합니다. 또한 부모-자식 쿼리(이 단원의 뒷부분에서 다룹니다)에 필요한 관계 이름을 제공합니다.

자식 대 부모 쿼리 만들기

이제 연락처와 계정에 자녀 대 부모 관계가 있다는 것을 압니다. 연락처는 하위이고 계정은 상위입니다. 모든 연락처(하위)와 각 연락처의 계정(상위) 이름을 반환하려면 하위 대 상위 쿼리가 필요합니다. 

자식 대 부모 쿼리에서 다음과 같이 점 표기법을 사용하여 자식 개체를 쿼리하고 부모 개체에서 필드를 가져옵니다.

SELECT Name, Account.Name FROM Contact

복사

이 SELECT 문은 Contact 개체를 쿼리합니다. SELECT 절에서 이름은 연락처의 이름 필드이고 Account.Name연락처와 관련된 계정의 이름 필드입니다.

자식에서 부모로 쿼리 실행

  1. 개발자 콘솔의 쿼리 편집기에서 다음을 입력합니다.
  2. SELECT Name, Account.Name FROM Contact복사
  3. 실행 을 클릭 합니다 .

결과의 처음 6개 행은 다음과 같아야 합니다.

쿼리 결과 - 총 행: 20
Name Account.Name
Rose Gonzales Edge Communications
Sean Forbes Edge Communications
Jack Rogers Burlington Textiles Corp of America
Pat Stumuller Pyramid Construction Inc.
Andy Young Dickenson plc
Tim Barr Grand Hotels & Resorts Ltd

두 번째 열에는 연락처의 상위 계정 개체에서 가져온 계정 이름이 표시됩니다. 

상위-하위 쿼리 생성

이제 부모 개체를 쿼리하고 자식 개체에서 필드를 가져오는 방법을 살펴보겠습니다. 부모 대 자식 쿼리에서 하위 쿼리를 사용하여 자식 개체에서 필드를 가져옵니다. 하위 쿼리는 괄호로 묶이고 다른 쿼리 내에 중첩된 SELECT 문입니다.

요구 사항이 다음과 같다고 가정합니다.

"모든 계정에 대해 계정 이름과 각 관련 연락처의 이름을 반환하십시오."

"of each related"를 읽을 때 우리는 관계 쿼리가 필요하다는 것을 압니다. Contact는 Account  자식 이므로 자식 개체의 하위 쿼리를 포함하는 부모 대 자식 관계 쿼리가 필요합니다. 

"모든 계정에 대해 계정 이름 반환" 요구 사항의 첫 번째 부분은 전체 쿼리의 외부 부분을 형성하는 기본 쿼리가 됩니다. 요구 사항의 두 번째 부분인 "각 관련 연락처의 이름"은 기본 쿼리 내에 중첩된 내부 쿼리인 하위 쿼리가 됩니다.

먼저 기본 쿼리를 정의합니다. SELECT Name FROM Account

다음으로 괄호 안에 하위 쿼리를 정의합니다. (SELECT Name FROM Contact)

그런 다음 하위 쿼리를 기본 쿼리의 두 번째 필드인 것처럼 배치합니다. Name 뒤에 쉼표를 추가하고 다음과 같이 하위 쿼리를 삽입합니다.

하위 쿼리 내에서 관련 개체의 필드 이름 대신 하위 관계 이름을 사용합니다. 따라서 마지막 단계로 다음 과 같이 Contacts개체 이름 대신 자식 관계 이름을 사용하도록 하위 쿼리를 변경합니다 Contact.

이 쿼리는 계정 이름과 모든 계정에 대한 모든 연락처 이름을 반환합니다. 분해해 보겠습니다.

이 쿼리는 세 부분으로 실행됩니다.

  1. 쿼리는 계정을 선택하고 계정 이름 필드를 가져옵니다. 이것이 메인 쿼리(외부 쿼리)입니다.
  2. 다음으로 쿼리는 계정의 관련 연락처를 살펴보고 각각에 대한 이름 필드를 가져옵니다. 그것이 하위 쿼리(내부 쿼리)입니다.
  3. 그런 다음 다음 계정으로 이동하여 모든 계정을 선택할 때까지 프로세스를 반복합니다.

상위-하위 쿼리 실행

  1. 쿼리 편집기에서 다음을 입력합니다.
  2. SELECT Name, (SELECT Name FROM Contacts) FROM Account복사
  3. 실행 을 클릭 합니다 .

결과의 처음 6개 행은 다음과 같아야 합니다.

쿼리 결과 - 총 행: 12
Name Contacts
Edge Communications [{"Name":"Rose Gonzalez"},{"Name":"Sean Forbes"}]
Burlington Textiles Corp of America [{"Name":"Jack Rogers"}]
Pyramid Construction Inc. [{"Name":"Pat Stumuller"}]
Dickenson plc [{"Name":"Andy Young"}]
Grand Hotels & Resorts Ltd [{"Name":"John Bond"},{"Name":"Tim Barr"}]
United Oil & Gas Corp. [{"Name":"Arthur Song"},{"Name":"Avi Green"},{"Name":"Lauren Boyle"},{"Name":"Stella Pavlova"}]

흥미로운! 쿼리 결과 창에는 계정 이름과 각 계정과 연결된 하위 연락처 레코드 모음이 표시됩니다. 관리자를 위한 객체 지향 프로그래밍 모듈 에서 맵에 대해 논의했기 때문에 이러한 유형의 컬렉션은 아마도 친숙해 보일 것입니다 

지도가 무엇인지 기억나지 않더라도 걱정하지 말고 검토해 봅시다. 맵 컬렉션에는 쉼표로 구분된 키-값 쌍이 포함됩니다. 키는 Name과 같은 필드 이름입니다. 키 다음에는 Jake Llorrac과 같은 값이 옵니다. 키 값 쌍은 계정과 관련된 연락처를 쿼리하는 중첩된 SELECT 문에 의해 반환됩니다.

하위 쿼리로 필터링

Forbes라는 성을 가진 관련 연락처가 있는 계정만 원한다고 가정합니다. 이것은 부모 개체 Account를 자식 개체 Contact의 값으로 필터링하려고 하기 때문에 까다롭습니다. 기본 쿼리 내에 하위 쿼리를 중첩한 것과 같은 방식으로 기본 쿼리의 WHERE 절에서 하위 쿼리(자식 개체의)를 사용할 수 있습니다. 하위 쿼리의 결과는 기본 쿼리에 대한 필터와 같은 역할을 합니다. 교차 필터에 익숙하다면 하위 쿼리에 WHERE 절을 추가하는 것은 보고서에서 교차 필터를 사용하는 것과 같습니다.

기존 쿼리로 시작합니다.
SELECT Name, (SELECT Name FROM Contacts) FROM Account

다음으로 성이 Forbes인 연락처에서 AccountId 필드를 가져오는 하위 쿼리가 필요합니다.

(SELECT AccountId FROM Contact WHERE LastName = 'Forbes')

연락처의 AccountId 필드가 필요한 이유가 궁금할 것입니다. 연락처의 AccountId 필드를 확인하여 계정과 관련된 연락처를 찾습니다. Contact 개체의 AccountId 필드와 Account 개체의 Id 필드가 동일한 값( Contact.AccountId = Account.Id)을 가질 때 연락처는 계정과 관련됩니다 . 따라서 Contact 개체를 쿼리하고 AccountId 값을 반환합니다. 연락처와 관련된 계정을 선택하기 위해 ID 필드에서 해당 값을 가진 계정을 찾습니다.

마지막으로 메인 쿼리에 WHERE 절을 추가합니다. 하위 쿼리에서 반환된 연락처의 AccountId 필드에 해당 ID가 있는 경우에만 계정 레코드를 선택하려고 합니다. 따라서 WHERE Id IN다음과 같이 하위 쿼리를 추가 합니다.

SELECT Name, (SELECT Name FROM Contacts) FROM Account WHERE Id IN (SELECT AccountId FROM Contact WHERE LastName = 'Forbes')

복사

이 쿼리는 네 가지 작업을 수행합니다. 

  1. 쿼리는 성이 Forbes인 연락처를 찾고 각 연락처의 AccountId 필드 값을 반환합니다. (WHERE 절 하위 쿼리가 이를 수행합니다.)
  2. 그런 다음 계정의 Id 필드에서 해당 AccountId의 값을 찾고 해당 계정의 이름을 가져옵니다. (메인 WHERE 절이 이를 수행합니다.)
  3. 그런 다음 쿼리는 계정의 관련 연락처를 살펴보고 각 연락처의 이름을 가져옵니다. (메인 쿼리의 하위 쿼리가 이를 수행합니다.)
  4. 마지막으로 기본 쿼리는 Forbes라는 성을 가진 관련 연락처가 있는 각 계정의 이름과 각 계정에 대해 모든 관련 연락처의 이름을 반환합니다.

필터링된 쿼리 실행

  1. 쿼리 편집기에서 다음을 입력합니다.
  2. SELECT Name, (SELECT Name FROM Contacts)
    FROM Account
    WHERE Id IN (SELECT AccountId FROM Contact WHERE LastName = 'Forbes')
  3. 실행 을 클릭 합니다 .

결과는 다음과 같아야 합니다.

요약

이제 표준 개체에 대해 올바른 유형의 관계 쿼리를 선택하고 작성하는 방법을 알게 되었습니다. 다음 단원에서는 사용자 지정 개체에 대한 관계 쿼리에 대해 알아봅니다.

 

Quiz

1. Which query returns the priority and related contact name for a case?

A.SELECT Name, Priority FROM Case

B.SELECT Priority, (SELECT Name FROM Contact) FROM Case

C.SELECT Contact.Name, Priority FROM Case

D.SELECT Name, Priority FROM Contact

 

2. True or false: To query a child object and get fields from the parent object, use a subquery.

A.True

B.False

 

사용자 지정 개체로 관계 쿼리 만들기

학습 목표

이 단원을 완료하면 다음을 수행할 수 있습니다.

  • 스키마 빌더에서 다이어그램을 해석하여 개체 관계를 식별합니다.
  • 사용자 지정 개체의 쿼리에 사용할 사용자 지정 관계 이름을 식별합니다.
  • 사용자 지정 개체에 대한 자식 대 부모 쿼리를 만듭니다.
  • 사용자 정의 개체에 대한 상위-하위 쿼리를 만듭니다.

함께 따라와 함께 트레일

이 단계를 진행하면서 강사와 함께 하고 싶으십니까? Trailhead Live에서 Trail Together 시리즈의 일부인 이 비디오를 보십시오. 

 

(이 클립은 51분 38초부터 시작되며, 되감기하여 단계의 시작 부분을 다시 보고 싶은 경우를 대비해 보세요.)

Trailhead Playground 시작 및 패키지 설치

이 모듈의 나머지 부분에 있는 예제 및 실습 활동에서는 DreamHouse라는 샘플 부동산 애플리케이션을 사용합니다. Trailhead Playground에 앱을 설치하고 샘플 데이터를 가져오겠습니다.

아직 열려 있지 않다면 Trailhead Playground를 시작하십시오. 조직에 패키지 설치라는 탭이 표시되면 좋습니다. 1단계로 건너뜁니다. 그렇지 않은 경우 앱 런처( 

)에서 Playground Starter를 찾아 열고 단계를 따릅니다. 당신이 놀이터 스타터 응용 프로그램이 표시되지 않는 경우, 복사 드림 하우스 패키지에이 링크를 체크 아웃 트레일의 기점 도전 완료하기 위해 패키지 나 응용 프로그램을 설치 트레일의 기점 도움말에 있습니다.

  1. 패키지 설치 탭을 클릭합니다 .
  2. 04tB00000009UeX필드에 붙여넣 습니다.
  3. 설치 를 클릭 합니다 .
  4. 선택 관리자를위한 설치 만 , 다음을 클릭합니다 설치 .
  5. 타사 액세스를 승인하라는 메시지가 표시되면 예, 액세스 권한을 부여합니다...  를 선택한 다음 계속 을 클릭 합니다.

패키지 설치가 완료되면 확인 페이지가 표시되고 플레이그라운드와 연결된 주소로 이메일이 전송됩니다.

드림하우스 데이터 가져오기

  1. 을 클릭 하고 검색 상자에 
    입력 Dream한 다음 DreamHouse  을 선택합니다 .
  2. 데이터 가져오기 탭을 클릭합니다 . (데이터 가져오기 탭이 표시되지 않으면 추가 목록을 확장합니다 .)
  3. 샘플 데이터 초기화 를 클릭 합니다 .
  4. 확인 대화 상자에서 확인 을 클릭 합니다.
  5. 속성 탭을 클릭하고 샘플 데이터에 익숙해집니다.

DreamHouse 스키마 살펴보기

지금까지는 표준 개체만 쿼리했습니다. 이제 사용자 지정 개체를 쿼리하는 방법에 대해 설명합니다. DreamHouse 앱에서 객체를 사용하므로 먼저 DreamHouse 스키마(데이터 모델)를 검토하여 데이터가 구조화되는 방식을 이해하겠습니다.

스키마 빌더 열기

  1. Trailhead Playground에서 을 클릭 
    하고 설정 을 선택 합니다.
  2. 개체 관리자를 클릭합니다 .
  3. 스키마 빌더 를 클릭합니다 .
  4. 개체 탭에서 모두 지우기 를 클릭 합니다 .
  5. Broker__c가 아닌 Broker가 표시되면 보기 옵션을 클릭 한 다음 요소 이름 표시 를 선택 합니다.
  6. 코드에서 필드 API 이름을 사용한다는 것을 기억하십시오. 요소 이름 표시는 필드 레이블 대신 필드 API 이름을 표시합니다. (사용자 정의 개체의 API 이름은 끝에 __c [underscore underscore c]가 추가된 사용자 정의 개체 이름입니다.)
  7. 다음에서 선택 목록에서 사용자 정의 개체 를 선택합니다 .
  8. Broker__c  Property__c 를 선택합니다 . 이것은 우리가 이 단원에서 사용하는 사용자 정의 개체입니다.
  9. 자동 레이아웃 을 클릭합니다 .
  10. 속성 필드를 검사합니다.
  11. Property__c 사용자 정의 개체에는 Picture__c 및 Broker__c라는 두 개의 사용자 정의 필드가 있습니다. (사용자 정의 필드의 API 이름은 끝에 __c [underscore underscore c]가 추가된 사용자 정의 필드 이름입니다.)
  12. Property__c를 Broker__c에 연결하는 관계 선 위로 마우스를 가져갑니다.
  13. Property__c 사용자 지정 개체의 Broker__c 사용자 지정 필드에서 Broker__c 사용자 지정 개체로의 조회 관계가 있습니다.
  14. Property__c 요소에서 톱니바퀴 아이콘을 클릭한 다음 개체 보기 를 선택 합니다.
    Property__c 개체를 표시하는 개체 관리자가 열립니다.
  15. 필드 및 관계 를 클릭합니다 .
  16. 브로커 필드 레이블을 클릭합니다 .
  17. 조회 옵션 섹션에서 하위 관계 이름을 찾습니다.

이제 Property__c가 Broker__c의 자식이고 속성과 브로커 간의 관계 이름이 Properties라는 것을 알고 있습니다. (관계 이름은 일반적으로 자식 개체 이름의 복수형임을 기억하십시오.)

사용자 정의 개체 쿼리

사용자 정의 개체를 쿼리하는 것은 표준 개체를 쿼리하는 것과 비슷하지만 몇 가지 차이점이 있습니다.

다음 요구 사항을 고려하십시오. 

"부동산 주소, 사진 및 할당된 중개인이 있는 모든 부동산 목록을 가져옵니다."

아주 간단하죠? Property__c 사용자 정의 개체를 쿼리하고 Address__c, Picture__c 및 Broker__c 사용자 정의 필드를 가져옵니다. 해 보자.

쿼리 만들기

  1. 쿼리 편집기에서 다음을 입력합니다.
  2. SELECT Address__c, Picture__c, Broker__c FROM Property__c복사
  3. 실행 을 클릭 합니다 .
    결과의 처음 6개 행은 다음과 같아야 합니다.
  4. Query Results - Total Rows: 18
    Address__c Picture__c Broker__c
    18 Henry st https://s3-us-west-1.amazonaws.com... a016g000007Yxfn...
    121 Harborwalk https://s3-us-west-1.amazonaws.com... a016g000007Yxfn...
    95 Gloucester st https://s3-us-west-1.amazonaws.com... a016g000007Yxfn...
    30 Peterborough st https://s3-us-west-1.amazonaws.com... a016g000007Yxfn...
    24 Pearl st https://s3-us-west-1.amazonaws.com... a016g000007Yxfn...
    503 Park Drive https://s3-us-west-1.amazonaws.com... a016g000007Yxfn...Notice that the contents of the Broker__c column are not very useful. That’s because the Broker__c field in the Property__c object is a lookup to the Broker object. Fields with lookup relationships contain the related object’s Id. To get the name of the Broker, we need a relationship query.

Broker__c 열의 내용은 그다지 유용하지 않습니다. Property__c 개체의 Broker__c 필드가 Broker 개체에 대한 조회이기 때문입니다. 조회 관계가 있는 필드에는 관련 개체의 Id 가 포함 됩니다. 브로커  이름 을 얻으려면 관계 쿼리가 필요합니다.

자식 대 부모 쿼리 만들기

Broker__c는 Property__c의 부모이므로 자식 대 부모 쿼리가 필요합니다. Broker__c 개체의 이름 필드를 가져오기 위해 관계 이름과 점 표기법을 사용합니다.

  1. 쿼리 편집기에서 다음과 같이 Broker__c를 Broker__c.Name으로 변경합니다.
  2. SELECT Address__c, Picture__c, Broker__c.Name FROM Property__c복사
  3. 실행 을 클릭 합니다 . (오류 메시지가 나타납니다.)
에러 메시지
필드 경로에서 'Broker__c' 관계를 이해하지 못했습니다. 사용자 지정 관계를 사용하려는 경우 사용자 지정 관계 이름 뒤에 '__r'을 추가해야 합니다.

이런! 무슨 일이에요? Broker__c는 Property 개체  사용자 정의 필드 임을 기억하십시오 . 우리가 원하는 것은 Broker__c 관련 객체 입니다. 

쿼리에서 사용자 지정 관계 이름 사용

Broker__c 관련 객체(Broker__c 필드 아님)를 지정하기 위해 __c를 __r(밑줄-밑줄-r)로 변경합니다. Broker__r은 사용자 지정 관계 이름입니다. 이는 Property__c에서 Broker__c 개체로의 관계를 탐색하려는 것을 나타냅니다. 쿼리의 이 부분은 "관련 Broker__c 사용자 지정 개체에서 이름 필드 가져오기"라고 말합니다. 쿼리를 업데이트해 보겠습니다.

  1. 쿼리 편집기에서 다음 과 같이 로 변경 Broker__c합니다 Broker__r.
  2. SELECT Address__c, Picture__c, Broker__r.Name FROM Property__c복사
  3. 실행 을 클릭 합니다 .

    결과의 처음 6개 행은 다음과 같아야 합니다.
  4. Query Results - Total Rows: 18
    Address__c Picture__c Broker__r.Name
    18 Henry st https://s3-us-west-1.amazonaws.com... Caroline Kingsley
    121 Harborwalk https://s3-us-west-1.amazonaws.com... Caroline Kingsley
    95 Gloucester st https://s3-us-west-1.amazonaws.com... Caroline Kingsley
    30 Peterborough st https://s3-us-west-1.amazonaws.com... Caroline Kingsley
    24 Pearl st https://s3-us-west-1.amazonaws.com... Michael Jones
    503 Park Drive https://s3-us-west-1.amazonaws.com... Michael Jones

훨씬 낫다. 이제 Id 대신 Broker 사용자 정의 개체의 Name 필드가 있습니다. 

상위-하위 쿼리 생성

관련 브로커와 함께 각 속성을 성공적으로 반환했습니다. 반대를 원하면 어떻게 합니까? 

요구 사항:

"각 중개인에게 할당된 모든 부동산의 주소와 가격으로 모든 중개인의 이름을 얻으십시오."

브로커 목록이 필요하기 때문에 기본 쿼리에서 Broker__c 개체를 쿼리합니다.

SELECT Name FROM Broker__c

복사

브로커는 부모이므로 부모 대 자식 쿼리에는 자식 개체의 하위 쿼리가 필요합니다. 하위 쿼리에서 하위 관계 이름을 사용합니다.

Property__c 개체의 하위 쿼리에 대한 관계 이름은 무엇입니까? Property 개체의 Broker 필드에 대한 세부 정보를 확인합니다.

하위 관계 이름은 속성입니다. 이것은 사용자 지정 관계이기 때문에 쿼리에서 사용할 때 __r( Properties__r)을 추가 합니다. 따라서 우리의 하위 쿼리(괄호 안)는 다음과 같습니다.

( SELECT Address__c, Price__c FROM Properties__r)

메인 쿼리에 하위 쿼리를 삽입하면 전체 쿼리는 다음과 같습니다.

SELECT Name, (SELECT Address__c, Price__c FROM Properties__r) FROM Broker__c

쿼리 실행

  1. 쿼리 편집기에서 다음을 입력합니다.
  2. SELECT Name, (SELECT Address__c, Price__c FROM Properties__r) FROM Broker__c복사
  3. 실행 을 클릭 합니다 .
    결과의 처음 8개 행은 다음과 같아야 합니다.

완벽한! 이제 모든 브로커 목록과 쉼표로 구분된 각 브로커 속성 목록이 있습니다. 

쿼리를 개발할 때 개발자 콘솔의 쿼리 편집기는 SOQL 쿼리를 테스트하고 조정할 수 있는 쉬운 방법을 제공한다는 점을 기억하십시오.

Create a Relationship Query

Use SOQL to identify properties listed with DreamHouse Realty in the last 30 days.

If you didn’t already install the DreamHouse package and import sample data, follow the instructions at the beginning of this unit to do that now.

  • Create a class
    • Name: PropertyUtility
  • Create a method
    • Name: newListedProperties
    • Keywords: public, static, and void
  • Create a list
    • Name: newPropList
  • Create a query and assign the query results to the list
    • Get this information:
      • The name of the property
      • The broker’s email address
      • How long the property has been on market
      (Hint: Use API names, not field names or field labels)
    • Object: Property
    • Condition: The property was listed within the last 30 days
  • Create a for loop that iterates through the query results
    • Object: Property
    • List name: newPropList
    • For each item, concatenate the property name, followed by a colon, followed by the broker’s email address: <Property Name> : <Broker Email>
    • Store the concatenated string in a variable named propEmail
    • Print the propEmail variable to the debug log


public class PropertyUtility {
    public static void newListedProperties(){
        List<Property__c> newPropList = [SELECT Name, Broker__r.Email__c,Days_On_Market__c FROM Property__c  WHERE Days_On_Market__c  <= 30];
        
        for (Property__c con : newPropList){
            String propEmail = '<' + con.Name+'>:<' + con.Broker__r.Email__c + '>';
            system.debug(propEmail);
        }
    }
}

 

 

Use Bind Variables and Aggregate Functions

Learning Objectives

After completing this unit, you’ll be able to:

  • Make a query dynamic by inserting Apex bind variables.
  • Use an aggregate function to roll up and summarize data in a query.
  • Apply grouping to query results.
  • Recognize when to use the WHERE clause vs. the HAVING clause.

Follow Along with Trail Together

Want to follow along with an instructor as you work through this step? Take a look at this video, part of the Trail Together series on Trailhead Live. 

 

(This clip starts at the 1:10:42 minute mark, in case you want to rewind and watch the beginning of the step again.)

Introduction

We have discussed how to write a basic SOQL query and how to formulate queries that include fields in parent or child objects. But, as you know, each application development project is unique. Knowing how to tailor business logic to solve a specific problem is important. 

Bind Variables

Using bind variables is one way to tailor your code. It’s similar to opening a form in the user interface and modifying an input field to search for certain results. Let’s look at an example in the DreamHouse app. You’re a realtor selling houses, and you want to review your inventory of properties priced under $200,000. So you write this query:

List<Property__c> property = [SELECT Id, Name, Price__c FROM Property__c WHERE Price__c < 200000];

Copy

That’s pretty simple—for you. But it’s static. This query always returns houses under $200,000. What about other realtors and potential buyers who can’t write SOQL queries and run them in the Developer Console? They need an easier way to filter houses by the price that’s right for them. How can you write one query that works for a buyer whose budget is $200,000 and another buyer whose budget is $800,000? That's where bind variables come in. A bind variable is an Apex variable that you use in a SOQL query. Use bind variables as placeholders for specific values to be provided later. 

 

This isn’t a new concept. In Object-Oriented Programming for Admins, you learned about using a parameter as a placeholder in a method. When you call the method, you pass in an argument that replaces the parameter. A bind variable in a query is like a parameter in a method. The bind variable is replaced by a specific value when the query runs.

Consider a bind variable named maxHomeValue. We declare the variable in Apex and then use the variable in a query, like this: 

Integer maxHomeValue = 200000; List<Property__c> property = [SELECT Name, Price__c FROM Property__c WHERE Price__c < :maxHomeValue];

Copy

Notice that in the query, the bind variable is preceded by a colon ( : ). This query returns the name and price from the property object. But the results are filtered based on the price of the home: WHERE Price__c < :maxHomeValue. The value of the bind variable, maxHomeValue, is set outside the query. Let’s look at this in action.

  1. In your Trailhead Playground, click 
    , type Dream in the Search box, and then select the DreamHouse app.
  2. Click Property Explorer.
    The Property Explorer searches for available properties based on the selected price range. The sliders accept values for the maxHomeValue and minHomeValue bind variables.
  3. Move the left slider from 200K to 550K.
  4. Move the right slider from 1.2M to 800K.

Each time a slider moves, its associated value is modified in the code through its bind variable. The query runs and adds the results to a list of properties displayed on the property explorer page.

Using bind variables in the WHERE clause allows you to set variable values in your code before the query runs. Bind variables make a query dynamic. To customize a query for each user, set bind variable values based on user input. As you continue modifying and reviewing code, you’ll discover many types of fields whose data is constantly changing.

Aggregate Functions

In reports, you use roll-up summary fields to calculate values from related records. For example, you might want to calculate the total number of properties, or the average or highest value of properties in a city. In SOQL, you use aggregate functions to perform those and other calculations. 

Aggregate Functions for SOQL Queries

Aggregate Function Description Example
COUNT() Returns the number of rows that are associated with the field SELECT COUNT(Name)
FROM Broker__c
COUNT_DISTINCT() Returns the number of unique rows that match the query criteria SELECT COUNT_DISTINCT(City__c)
FROM Property__c
MIN() Returns the minimum value of a field SELECT MIN(Days_On_Market__c)
FROM Property__c
MAX() Returns the maximum value of a field SELECT MAX(Beds__c)
FROM Property__c
AVG() Returns the average value of a numeric field SELECT City__c, AVG(Days_On_Market__c)
FROM Property__c
GROUP BY City__c
SUM() Returns the total value of a numeric field SELECT SUM(Price__c), Broker__r.Name
FROM Property__c
GROUP BY Broker__r.Name

Let’s use properties in a city as an example. Suppose we start with this simple query:

SELECT City__c FROM Property__c

Copy

The query returns the city for each of 18 properties.

Because we don’t want the entire list of cities, modify the query to use an aggregate function. To get the total number of properties use the COUNT() function.

The aggregate function goes in the SELECT clause of a query, like this:

The parentheses after the function name contain the name of the field to use in the calculation. In this example, we’re counting the values in the City__c field.

Run a COUNT() Query

  1. In the Query Editor, type:
  2. SELECT City__c FROM Property__cCopy
  3. Click Execute.
    Your query results should have 18 rows with the city for each property.
  4. Edit the query so that the City__c field is inserted in the COUNT() function, like this:
  5. SELECT COUNT(City__c) FROM Property__cCopy
  6. Click Execute.
    Your query result should be 18, the number of properties based on the City__c field.

If you noticed that all of the 18 properties are in only 3 cities, you might be wondering why the count is 18 instead of 3. That’s because the COUNT() function counts all values, which often includes multiple records with the same value.

Suppose we want to assign one broker to all of the properties in one city. How many brokers do we need? Put another way, how many unique cities do the 18 properties represent? To count only unique cities, we need another function. (When you hear “unique,” think “distinct.”)

COUNT_DISTINCT() is similar to COUNT() except that it returns only unique values (no duplicates).

Run a COUNT_DISTINCT Query 

  1. In the Query Editor, edit the query to use the COUNT_DISTINCT() function, like this:
  2. SELECT COUNT_DISTINCT(City__c) FROM Property__cCopy
  3. Click Execute.
    Now your result should be 3, the number of unique City__c values among all properties.

Cambridge, Boston, and Brookline are the only unique values found in the City__c field. Note that the COUNT() and COUNT_DISTINCT() functions are case-sensitive. That means that Cambridge is not a duplicate of cambridge. Cambridge and cambridge are considered two unique values.   

MIN(), MAX(), AVG(), and SUM()

Other useful aggregate functions include MIN(), MAX(), AVG(), and SUM().

The MIN() and MAX() functions are straightforward. MIN() finds the minimum (lowest) value and MAX() finds the maximum (highest) value. But there’s something unique about these functions. They can handle dates and times as well as numbers. 

  1. In the Query Editor, type:
  2. SELECT MIN(Date_Listed__c) FROM Property__cCopy
  3. Click Execute.

The MIN() function returns the earliest date. The MAX() function returns the latest (most recent) date. 

The MIN() and MAX() functions also recognize the sort order of picklist values, so you can find the first or last value in a picklist.

The AVG() function calculates the average of all values. The SUM() function calculates the sum of all values. Because both of these functions perform calculations, they work only with fields that contain numeric values.

Group the Results of Aggregate Functions

After calculating values based on aggregated data, you might want to report results in groups, as you do in summary reports. To group values in a SOQL query, use the GROUP BY clause. For instance, a customer of DreamHouse Realty wants to know which brokers have sold (closed) a property.

Get Hands-on with the GROUP BY Clause

Before we group some aggregate results, we need to update a few property listings. DreamHouse Realty had an uptick in sales for the week. Update the following properties.

  1. In the DreamHouse app, click the Properties tab.
  2. Click the 30 Peterborough St. property.
  3. Change the Status to Closed.
  4. Click Save.
  5. Repeat steps 2–4 for these properties:
  6. 127 Endicott St.
    650 Kendall St.

The DreamHouse app is up to date. Next, use the GROUP BY clause in a query.

  1. In the Query Editor, type:SELECT MAX(Status__c), Broker__r.Name FROM Property__c GROUP BY Broker__r.NameCopy
  2. Click Execute.
    Your results should have eight rows.

 

Remember, this query groups properties by broker. For each broker’s properties, we list the most advanced Status__c value. That’s the Status picklist value that is closest to the final picklist value. We want brokers who have sold properties, so we’ll narrow the results even more. Back to the drawing board. 

Filter the Results of Aggregate Functions

Another way to narrow results is to use a HAVING clause. The HAVING clause filters the results returned by an aggregate function. 

Hmm… this sounds like something we can use to find brokers who sold properties. Our previous query returned a list of brokers who have properties in any status. Try using the HAVING clause to narrow those results. 

  1. In the Query Editor, type:
  2. SELECT MAX(Status__c), Broker__r.Name FROM Property__c GROUP BY Broker__r.Name HAVING MAX(Status__c) = 'Closed'Copy
  3. Click Query. You should get a list of three brokers.

Yes! There we go. Using the HAVING clause narrows results to properties with the Closed status. Great work!

The WHERE clause is a lot like the HAVING clause, right? Here’s how to decide when to use WHERE and when to use HAVING. 

  • The WHERE clause filters records in a SOQL query that has no aggregate function.
  • The HAVING clause filters the results after data is aggregated by an aggregate function.

As you learned in this module, SOQL is a great tool for accessing data in your Salesforce org. As you continue to build and expand your Apex coding skills, you’ll encounter many opportunities to use your SOQL knowledge. As you do, remember that you can find details, examples, and more information about Apex and SOQL in the resources provided in this module. Now, go forth and query… with SOQL.

 

 

Quiz

1. Which punctuation identifies a bind variable in a query?

A..

B.:

C.<>

D.[]

 

2. Which SOQL query returns the highest priced home in each city?

A.SELECT COUNT_DISTINCT(Address__c),Price__c FROM Property__c GROUP BY City__c

B.SELECT COUNT_DISTINCT(Price__c), City__c FROM Property__c Group BY City__c

C.SELECT MAX(Price__c), City__c FROM Property__c Group BY City__c

D.SELECT MAX(City__c), Price__c FROM Property__c

Check the Quiz to Earn 100 Points

Second attempt ear

 

 

 

 

 

 

 

 

반응형