Pierwsze zapytania SOQL

Gdzie i jak uruchamiać zapytania (Salesforce Inspector, Developer Console, VS Code, CLI) oraz podstawy SOQL: filtrowanie, sortowanie, relacje i agregacje.

Lekcja 1 z 713 min czytania

SOQL (Salesforce Object Query Language) to język zapytań do danych w Salesforce. Jeśli znasz SQL, poczujesz się jak w domu, z kilkoma ważnymi różnicami:

  • SOQL służy tylko do odczytu danych,
  • nie ma klasycznych złączeń (JOIN). Powiązane dane pobierasz przez relacje,
  • zawsze wymieniasz pola, które chcesz pobrać. Nie ma odpowiednika SELECT * znanego z SQL.

SOQL przydaje się nie tylko programistom. Piszesz w nim zapytania do generatorów dokumentów, takich jak PDF Butler, eksportujesz dane do analizy i szybko sprawdzasz, co naprawdę jest w bazie. Ten kurs prowadzi od podstaw do zapytań, których użyjesz w codziennej pracy.

Gdzie uruchamiać zapytania?

Zapytanie SOQL możesz uruchomić w kilku miejscach. Na start wystarczy jedno z dwóch pierwszych.

NarzędzieDla kogoCo trzeba zainstalować
Salesforce Inspectoradministratorzy, konsultanci, analitycywtyczkę do przeglądarki
Developer Consolekażdy, kto ma do niej dostęp w orgunic, jest wbudowana w Salesforce
Visual Studio Codeprogramiściedytor, Salesforce CLI i rozszerzenia Salesforce
Salesforce CLIprogramiści, automatyzacja eksportówprogram wiersza poleceń

Salesforce Inspector

  1. Otwórz dowolną stronę Salesforce. Przy prawej krawędzi okna kliknij małą zakładkę ze strzałką (1).
  2. W okienku wtyczki kliknij Data Export (2). Otworzy się nowa karta przeglądarki.

Salesforce Inspector: strzałka przy prawej krawędzi strony i przycisk Data Export w okienku wtyczki

  1. Wpisz zapytanie w pole Export Query i kliknij Run Export albo naciśnij Ctrl + Enter (3).
  2. Wyniki pojawią się w tabeli poniżej. Przyciskiem Copy (Excel) (4) skopiujesz je do arkusza.

Salesforce Inspector, karta Data Export: zapytanie, przycisk Run Export i kopiowanie wyników

Jak zainstalować wtyczkę i co jeszcze potrafi, pokazujemy w następnej lekcji. Na Inspectorze ćwiczymy w całym kursie.

Developer Console

  1. Kliknij koło zębate w prawym górnym rogu Salesforce (1) i wybierz Developer Console (2). Konsola otworzy się w osobnym oknie. Jeśli nic się nie dzieje, sprawdź, czy przeglądarka nie zablokowała wyskakującego okna.

Menu koła zębatego w Salesforce z opcją Developer Console

  1. Na dole konsoli kliknij zakładkę Query Editor (3).
  2. Wpisz zapytanie i kliknij Execute (4).
  3. Wyniki pojawią się w górnej części okna jako tabela Query Results (5).

Developer Console: zakładka Query Editor, przycisk Execute i tabela Query Results

Nie widzisz Developer Console w menu? Konsola wymaga odpowiednich uprawnień, więc zwykli użytkownicy często jej nie mają. W darmowym orgu do nauki jesteś administratorem i masz do niej dostęp.

Visual Studio Code

Ta opcja jest dla osób, które piszą też kod w Salesforce.

  1. Zainstaluj Visual Studio Code, Salesforce CLI i rozszerzenie Salesforce Extension Pack.
  2. Otwórz paletę poleceń (Ctrl + Shift + P), utwórz projekt poleceniem SFDX: Create Project i połącz go z orgiem poleceniem SFDX: Authorize an Org.
  3. Wpisz zapytanie w dowolnym pliku, zaznacz je i uruchom polecenie SFDX: Execute SOQL Query with Currently Selected Text. Wynik pojawi się w panelu Output.

Salesforce CLI

Wiersz poleceń przydaje się, gdy ten sam eksport robisz regularnie albo chcesz go zautomatyzować.

  1. Zainstaluj Salesforce CLI. Polecenia zaczynają się od sf.
  2. Zaloguj się do orga. Otworzy się przeglądarka ze stroną logowania Salesforce:
sf org login web --alias nauka
  1. Uruchom zapytanie:
sf data query --query "SELECT Id, Name FROM Account LIMIT 5" --target-org nauka
  1. Zapisz wynik do pliku CSV, który otworzysz w Excelu:
sf data query --query "SELECT Id, Name FROM Account" --target-org nauka --result-format csv > konta.csv

Twoje pierwsze zapytanie

Zanim przejdziesz dalej, uruchom w Inspectorze albo w Developer Console proste zapytanie:

SELECT Id, Name FROM Account LIMIT 10

Jeśli zobaczysz tabelę z firmami ze swojego orga, wszystko działa. Teraz poznasz składnię, która za tym stoi.

Przykładowe dane

Wszystkie przykłady w tej lekcji działają na tych samych, małych danych: 6 firm i 5 kontaktów. Dzięki temu przy każdym zapytaniu łatwo porównasz dane wejściowe z wynikiem.

Obiekt Account (firmy):

NameIndustryBillingCityAnnualRevenue
Acme PolskaTechnologyWarszawa5 000 000
Beta FinanseFinanceKraków12 000 000
Cyfrowy DomTechnologyGdańsk800 000
Delta RetailRetailWarszawa3 500 000
Echo SoftwareTechnologyKraków2 200 000
Fala MediaMediaWarszawa(puste)

Obiekt Contact (kontakty), powiązany z firmą polem AccountId:

FirstNameLastNameFirma (Account)
AnnaNowakAcme Polska
PiotrKowalskiAcme Polska
EwaWiśniewskaBeta Finanse
JanZielińskiEcho Software
MartaLewandowska(brak firmy)

Dwie uwagi do tabel z wynikami. Kwoty są sformatowane dla czytelności, a Salesforce zwraca je jako zwykłe liczby, np. 5000000. Bez ORDER BY Salesforce nie gwarantuje kolejności rekordów, więc w takich wynikach pokazujemy je w kolejności z tabeli wejściowej.

Chcesz sprawdzić przykłady u siebie? Utwórz te firmy i kontakty w swoim orgu do nauki: ręcznie albo importem z pliku CSV, jak w lekcji Praca z rekordami i widokami list. Wartości Technology, Finance, Retail i Media są na standardowej liście branż.

Podstawowa składnia

SELECT Id, Name, Industry
FROM Account
WHERE Industry = 'Technology'
ORDER BY Name
LIMIT 10
  • SELECT: pola do pobrania (nazwy API, nie etykiety),
  • FROM: obiekt,
  • WHERE: warunki,
  • ORDER BY: sortowanie,
  • LIMIT: maksymalna liczba wyników.

Przykład 1. Wybór pól

SELECT Name, Industry
FROM Account

Co zwróci: wszystkie firmy, bo nie ma warunku WHERE, ale tylko dwie wskazane kolumny. Pozostałe pola, np. miasto i przychód, nie trafią do wyniku.

Wynik (6 rekordów):

NameIndustry
Acme PolskaTechnology
Beta FinanseFinance
Cyfrowy DomTechnology
Delta RetailRetail
Echo SoftwareTechnology
Fala MediaMedia

Filtrowanie

W warunkach WHERE możesz używać m.in.:

  • porównań: =, !=, <, >, <=, >=,
  • dopasowania tekstu: Name LIKE 'Acme%',
  • listy wartości: Industry IN ('Technology', 'Finance'),
  • łączenia warunków: AND, OR, NOT.

Przykład 2. Równość

SELECT Name, BillingCity
FROM Account
WHERE Industry = 'Technology'

Co zwróci: tylko firmy z branży Technology. Pozostałe rekordy odpadają już na etapie warunku.

Wynik (3 rekordy):

NameBillingCity
Acme PolskaWarszawa
Cyfrowy DomGdańsk
Echo SoftwareKraków

Przykład 3. Porównanie liczb i puste pola

SELECT Name, AnnualRevenue
FROM Account
WHERE AnnualRevenue > 3000000

Co zwróci: firmy z przychodem powyżej 3 milionów. Uwaga na Fala Media: ma puste pole przychodu, a puste pole nie spełnia żadnego porównania liczbowego, więc nie trafi do wyniku.

Wynik (3 rekordy):

NameAnnualRevenue
Acme Polska5 000 000
Beta Finanse12 000 000
Delta Retail3 500 000

Jeśli chcesz znaleźć właśnie firmy bez przychodu, użyj warunku WHERE AnnualRevenue = null.

Przykład 4. Łączenie warunków

SELECT Name, Industry, BillingCity
FROM Account
WHERE BillingCity IN ('Warszawa', 'Kraków')
AND Industry != 'Retail'

Co zwróci: firmy z Warszawy lub Krakowa, z wyjątkiem branży Retail. Oba warunki muszą być spełnione jednocześnie, więc Delta Retail (Warszawa, ale Retail) odpada.

Wynik (4 rekordy):

NameIndustryBillingCity
Acme PolskaTechnologyWarszawa
Beta FinanseFinanceKraków
Echo SoftwareTechnologyKraków
Fala MediaMediaWarszawa

Daty

Przy datach przydają się literały dat, które Salesforce przelicza za Ciebie:

SELECT Name, CloseDate, Amount
FROM Opportunity
WHERE CloseDate = THIS_QUARTER
AND StageName = 'Closed Won'

Inne przydatne literały to TODAY, LAST_N_DAYS:30 czy THIS_YEAR. Szczegóły i więcej przykładów znajdziesz w lekcji o filtrowaniu.

Sortowanie i limit

Przykład 5. Sortowanie malejąco

SELECT Name, AnnualRevenue
FROM Account
ORDER BY AnnualRevenue DESC NULLS LAST

Co zwróci: wszystkie firmy, od najwyższego przychodu do najniższego. DESC oznacza sortowanie malejące, a NULLS LAST przenosi firmy z pustym przychodem na koniec listy.

Wynik (6 rekordów):

NameAnnualRevenue
Beta Finanse12 000 000
Acme Polska5 000 000
Delta Retail3 500 000
Echo Software2 200 000
Cyfrowy Dom800 000
Fala Media(puste)

Przykład 6. Sortowanie po dwóch polach

SELECT Name, BillingCity
FROM Account
ORDER BY BillingCity, Name

Co zwróci: firmy posortowane najpierw alfabetycznie po mieście, a w ramach tego samego miasta po nazwie. Bez DESC sortowanie jest rosnące.

Wynik (6 rekordów):

NameBillingCity
Cyfrowy DomGdańsk
Beta FinanseKraków
Echo SoftwareKraków
Acme PolskaWarszawa
Delta RetailWarszawa
Fala MediaWarszawa

Przykład 7. Limit, czyli „pierwsze N”

SELECT Name, AnnualRevenue
FROM Account
ORDER BY AnnualRevenue DESC NULLS LAST
LIMIT 3

Co zwróci: trzy firmy z najwyższym przychodem. To samo zapytanie co w przykładzie 5, ale LIMIT 3 ucina wynik po trzecim rekordzie. Bez ORDER BY dostałbyś trzy przypadkowe firmy.

Wynik (3 rekordy):

NameAnnualRevenue
Beta Finanse12 000 000
Acme Polska5 000 000
Delta Retail3 500 000

Zapytania po relacjach

Przykład 8. Od dziecka do rodzica

Pola rekordu nadrzędnego pobierasz przez kropkę:

SELECT FirstName, LastName, Account.Name, Account.Industry
FROM Contact

Co zwróci: wszystkie kontakty, a przy każdym nazwę i branżę jego firmy. Marta Lewandowska nie ma firmy, więc jej pola firmy będą puste. Zapytanie nie zwróci błędu.

Wynik (5 rekordów):

FirstNameLastNameAccount.NameAccount.Industry
AnnaNowakAcme PolskaTechnology
PiotrKowalskiAcme PolskaTechnology
EwaWiśniewskaBeta FinanseFinance
JanZielińskiEcho SoftwareTechnology
MartaLewandowska(puste)(puste)

Pól rodzica możesz też używać w warunkach. Po dopisaniu WHERE Account.Industry = 'Technology' zostaną tylko Anna Nowak, Piotr Kowalski i Jan Zieliński.

Przykład 9. Od rodzica do dzieci

Rekordy podrzędne pobierasz podzapytaniem, w którym używasz nazwy relacji w liczbie mnogiej:

SELECT Name, (SELECT FirstName, LastName FROM Contacts)
FROM Account
WHERE BillingCity = 'Warszawa'

Co zwróci: firmy z Warszawy, a przy każdej listę jej kontaktów. Podzapytanie nie filtruje firm: Delta Retail i Fala Media nie mają kontaktów, ale i tak są w wyniku, tylko z pustą listą.

Wynik (3 rekordy):

NameContacts (podzapytanie)
Acme PolskaAnna Nowak, Piotr Kowalski
Delta Retail(brak kontaktów)
Fala Media(brak kontaktów)

W relacjach niestandardowych nazwa relacji kończy się na __r, np. Seller__r.Name albo podzapytanie FROM Offers__r. Dokładną nazwę relacji sprawdzisz w ustawieniach pola w Object Manager.

Agregacje

Funkcje agregujące nie zwracają pojedynczych rekordów, tylko podsumowania: liczby, sumy, średnie. GROUP BY dzieli rekordy na grupy i liczy wynik dla każdej z nich.

Przykład 10. Liczenie w grupach

SELECT Industry, COUNT(Id) liczba
FROM Account
GROUP BY Industry

Co zwróci: po jednym wierszu na każdą branżę i liczbę firm w tej branży. liczba to alias, czyli własna nazwa kolumny wyniku. W SOQL piszesz go bez słowa AS.

Wynik (4 wiersze):

Industryliczba
Technology3
Finance1
Retail1
Media1

Przykład 11. Suma w grupach

SELECT BillingCity, SUM(AnnualRevenue) przychod
FROM Account
GROUP BY BillingCity

Co zwróci: łączny przychód firm z każdego miasta. SUM pomija puste wartości: w Warszawie sumują się tylko Acme Polska i Delta Retail, bo Fala Media nie ma przychodu.

Wynik (3 wiersze):

BillingCityprzychod
Warszawa8 500 000
Kraków14 200 000
Gdańsk800 000

Przykład 12. Filtrowanie grup: HAVING

SELECT BillingCity, COUNT(Id) liczba
FROM Account
GROUP BY BillingCity
HAVING COUNT(Id) > 1

Co zwróci: tylko miasta, w których jest więcej niż jedna firma. WHERE filtruje pojedyncze rekordy przed grupowaniem, a HAVING filtruje gotowe grupy. Gdańsk ma jedną firmę, więc odpada.

Wynik (2 wiersze):

BillingCityliczba
Warszawa3
Kraków2

SOQL w kodzie Apex

W Apex zapytanie wpisujesz w nawiasach kwadratowych, a zmienne przekazujesz z dwukropkiem:

String branza = 'Technology';
List<Account> konta = [
    SELECT Id, Name
    FROM Account
    WHERE Industry = :branza
    LIMIT 10
];
System.debug(konta.size());

Taka zmienna (bind variable) chroni też przed wstrzykiwaniem niebezpiecznych wartości do zapytania.

Ćwiczenie

Korzystając z obiektów Nieruchomość (Property__c) i Oferta (Offer__c) z modułu 2 kursu Podstawy Salesforce, napisz zapytania, które:

  1. Zwracają wszystkie nieruchomości z ceną wyższą niż 500 000, posortowane od najdroższej.
  2. Zwracają nieruchomości o statusie Dostępna, które są dostępne od dnia przypadającego w tym roku.
  3. Dla każdej nieruchomości zwracają nazwisko sprzedającego i listę ofert z kwotami.

Podpowiedź do zadania 3: zacznij od SELECT Name, Seller__r.LastName, (SELECT ... FROM Offers__r) FROM Property__c. Kwotę oferty zapisuje pole Amount__c.

Sprawdź się

Przewidź wynik na przykładowych danych z początku lekcji, a dopiero potem rozwiń odpowiedź.

1. Które firmy zwróci to zapytanie?

SELECT Name FROM Account WHERE BillingCity = 'Warszawa' AND AnnualRevenue > 1000000
Pokaż odpowiedź

Acme Polska i Delta Retail. Fala Media też jest z Warszawy, ale ma puste pole przychodu, więc nie spełnia porównania liczbowego.

2. Co zwróci to zapytanie?

SELECT Industry, COUNT(Id) liczba FROM Account WHERE BillingCity != 'Gdańsk' GROUP BY Industry
Pokaż odpowiedź

WHERE usuwa firmę Cyfrowy Dom z Gdańska jeszcze przed grupowaniem, więc w branży Technology zostają dwie firmy:

Industryliczba
Technology2
Finance1
Retail1
Media1

3. Nazwiska których kontaktów zwróci to zapytanie?

SELECT LastName FROM Contact WHERE Account.BillingCity = 'Kraków'
Pokaż odpowiedź

Wiśniewska i Zieliński, bo ich firmy (Beta Finanse i Echo Software) są z Krakowa. Lewandowska odpada, bo nie ma przypisanej firmy.

Podsumowanie

  • SOQL tylko odczytuje dane i zawsze wymaga wskazania pól.
  • WHERE filtruje rekordy, ORDER BY ustala kolejność, a LIMIT ucina wynik. Bez ORDER BY kolejność nie jest gwarantowana.
  • Puste pola nie spełniają porównań w WHERE, a funkcje takie jak SUM je pomijają.
  • Relacje obsługujesz kropką (do rodzica) albo podzapytaniem (do dzieci). Podzapytanie nie usuwa rodziców bez dzieci.
  • Agregacje z GROUP BY zwracają podsumowania zamiast rekordów, a HAVING filtruje gotowe grupy.

Następny krok: zainstalujesz Salesforce Inspector, w którym przećwiczysz wszystkie zapytania z tego kursu. Każdy temat z tej lekcji, czyli filtrowanie, relacje i agregacje, rozwijamy potem w osobnej lekcji.