PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

nieprawidłowe odniesienie do wpisu klauzuli FROM dla tabeli w zapytaniu Postgres

Wyjaśnienie błędu

Bezpośrednią przyczyną komunikatu o błędzie jest to, że każde jawne JOIN wiąże mocniej niż przecinek (, ), co w przeciwnym razie jest równoważne z CROSS JOIN , ale (zgodnie z dokumentacją ):

Pogrubienie focus mine.
To jest przyczyna twojego błędu. możesz napraw to:

FROM  appointment_intakes
CROSS JOIN LATERAL jsonb_object_keys(data #> '{products}') keys
INNER JOIN appointment_intake_users ON ...

Ale to nie był jedyny problem. Czytaj dalej.

Można by argumentować, że Postgres powinien widzieć, że LATERAL ma sens tylko w połączeniu ze stołem po lewej stronie. Ale tak nie jest.

Założenie

Dodałem aliasy tabel i zakwalifikowałem wszystkie nazwy kolumn jako podejrzane. Będąc przy tym, uprościłem odwołania JSON i przyciąłem trochę szumu.To zapytanie jest nadal niepoprawne :

SELECT i.data ->> 'id'          AS id,
       i.data ->> 'name'        AS name,
       i.data ->> 'curator'     AS curator,
       i.data ->  '$isValid'    AS "$isValid",
       i.data ->  'customer'    AS customer,
       i.data ->  '$createdTS'  AS "$createdTS",
       i.data ->  '$updatedTS'  AS "$updatedTS",
       i.data ->  '$isComplete' AS "$isComplete",
       count(k.keys)::numeric   AS "numProducts",
       u.created_at
FROM   appointment_intakes i
     , jsonb_object_keys(i.data -> 'products') AS k(keys)
JOIN   appointment_intake_users u ON u.appointment_intake_id = i.id
#{where_clause}
GROUP  BY i.id

Nieprzetworzone zapytanie

W oparciu o powyższe i kilka innych założeń rozwiązaniem może być wykonanie liczenia w podzapytaniu:

SELECT i.data ->> 'id'          AS id,
       i.data ->> 'name'        AS name,
       i.data ->> 'curator'     AS curator,
       i.data ->  '$isValid'    AS "$isValid",
       i.data ->  'customer'    AS customer,
       i.data ->  '$createdTS'  AS "$createdTS",
       i.data ->  '$updatedTS'  AS "$updatedTS",
       i.data ->  '$isComplete' AS "$isComplete",
       (SELECT count(*)::numeric
        FROM   jsonb_object_keys(i.data -> 'products')) AS "numProducts",
       min(u.created_at)        AS created_at
FROM   appointment_intakes i
JOIN   appointment_intake_users u ON u.appointment_intake_id = i.id
--     #{where_clause}
GROUP  BY i.id;

Ponieważ potrzebujesz tylko licznika, przekonwertowałem Twój LATERAL połączyć w skorelowane podzapytanie, unikając w ten sposób różnych problemów wynikających z wielu połączonych łączeń 1:n. Więcej:

potrzebujesz aby poprawnie uciec przed identyfikatorami, użyj przygotowanej instrukcji i przekaż wartości jako wartości. Nie łącz wartości w ciągu zapytania. To zaproszenie do losowych błędów lub wstrzyknięcia SQL ataki. Ostatni przykład dla PHP:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rails:wdrażanie do Heroku, wiele problemów

  2. Nie znaleziono obrazu Psycopg2

  3. postgresql 9.3. Grupuj według bez wszystkich kolumn

  4. PostgreSQL:FATAL - Uwierzytelnienie peera nie powiodło się dla użytkownika (PG::ConnectionBad)

  5. Lista kontrolna zgodności SOx dla PostgreSQL