Postgres Interogarea/filtrare JSONB cu tablouri imbricate

0

Problema

Mai jos este proba mea cerință

Vreau clienții care îndeplinesc toate condițiile de mai jos

  1. În țară, "xyz", constituite între 2019 și 2021.
  2. Ar trebui să aibă cel puțin un cont cu echilibru intre 10000 si 13000 și de ramură este "abc" și datele tranzacțiilor între 20200110 și 20210625. Acesta este formatat și stocate ca număr
  3. Ar trebui să fie cu cel puțin o adresă în statul "state1" și coduri pin între 625001 și 625015

Mai jos este tabelul structura

        CREATE TABLE IF NOT EXISTS customer_search_ms.customer
        (
            customer_id integer,
            customer_details jsonb
        )
    

Pot exista milioane de rânduri în tabel. Am creat GIN index de tip jsonb_ops pe customer_details coloana ca ne-ar fi, de asemenea, verificarea existenței condițiilor și gama de comparație

Mai jos este o mostră de date în customer_data JSONB coloana

customer_id : 1

    {
        "customer_data": {
            "name": "abc",
            "incorporated_year": 2020,
            "country":"xyz",
            "account_details": [
                {
                    "transaction_dates": [
                        20180125, 20190125, 20200125,20200525
                    ],
                    "account_id": 1016084,
                    "account_balance": 2000,
                    "account_branch": "xyz"
                },
                {
                    "transaction_dates": [
                        20180125, 20190125, 20200125
                    ],
                    "account_id": 1016087,
                    "account_balance": 12010,
                    "account_branch": "abc"
                }
            ],
            "address": [
                {
                    "address_id": 24739,
                    "door_no": 4686467,
                    "street_name":"street1",
                    "city": "city1",
                    "state": "state1",
                    "pin_code": 625001
                },
                {
                    "address_id": 24730,
                    "door_no": 4686442,
                    "street_name":"street2",
                    "city": "city1",
                    "state": "state1",
                    "pin_code": 625014
                }
            ]
        }
    }

Acum întrebare ți-am scris mai sus este

SELECT  c.customer_id,
        c.customer_details
FROM customer_search_ms.customer c
WHERE c.customer_details @@ CAST('$.customer_data.country ==  "xyz" && $.customer_data.incorporated_year >= 2019 && $.customer_data.incorporated_year <= 2021 ' AS JSONPATH)
AND c.customer_details @? CAST('$.customer_data.account_details[*] ? (@.account_balance >=  10000) ? (@.account_balance <=  13000) ?(@.account_branch ==  "abc") ? (@.transaction_dates >=  20200110) ? (@.transaction_dates <=  20210625)' AS JSONPATH)
AND c.customer_details @? CAST('$.customer_data.address[*] ? (@.state ==  "state1") ? (@.pin_code >=  625001) ? (@.pin_code <= 625015)  ' AS JSONPATH)

Să se ocupe de mai sus scenariu este cel mai bun mod de a scrie. Este posibil să se combine toate cele 3 criterii (client/cont/adresa) într-o singură expresie? Tabelul va avea milioane de rânduri. Eu sunt de părere având-o ca o expresie și lovind DB va oferi cea mai bună performanță. Este posibil să se combine aceste 3 condiții ca o expresie

1

Cel mai bun răspuns

0

Interogare nu-mi dea eroare raportați. Mai degrabă, se ruleaza, dar nu dau "greșit" rezultatele în comparație cu ceea ce vrei. Există mai multe greșeli în ea, care nu sunt erori de sintaxă, dar da rezultate greșite.

Prima jsonpath arata bine. Este o expresie Booleană, și @@ verifică dacă această expresie dă true.

A doua jsonpath are două probleme. Se dă o listă de obiecte care se potrivesc condiții. Dar obiectele nu sunt boolean, deci @@ va fi nefericit și a reveni SQL NULL, care este tratat la fel ca false aici. În schimb, aveți nevoie pentru a testa dacă lista este goală. Aceasta este ceea ce @? are, deci, de a folosi că în loc de @@. De asemenea, datele dvs. sunt stocate ca de 8 cifre, numere întregi, dar sunt comparându-le cu 8-șiruri de caractere. În jsonpath, astfel de tip cruce comparații randament JSON null, care este tratat la fel ca false aici. Deci, aveți nevoie pentru a schimba de stocare la siruri de caractere, sau schimba literali acestea sunt comparate în numere întregi.

A treia jsonpath are, de asemenea, @@ problema. Și are inversa de tip problemă, aveți pin_code stocate ca siruri de caractere, dar sunt de testare-le împotriva numere întregi. În cele din urmă au 'pin_code' scris greșit într-un singur eveniment.

2021-11-24 20:58:29

Multumesc Janes. Am corectat codul și datele în original post. Din cauza naturii confidențiale a trebuit să-post fierte date si a facut o greseala in asta. Eu nu sunt capabil de a reproduce eroarea scenariu. Nu există nici o mai bună abordare pentru interogare dat mai sus cu 3 condiții în clauza where. Gândirea mea este daca eu sunt capabil să-l facă ca o singură condiție în loc de 3, acesta va fi mai bine. Orice sfat va fi de mare ajutor pentru mine. Multumesc
Balaji Govindan

În alte limbi

Această pagină este în alte limbi

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................