Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Czy można używać GROUP BY ze zmiennymi wiązania?

Sugeruję przepisać instrukcję tak, aby był tylko jeden argument bind. To podejście jest trochę brzydkie, ale zwraca zestaw wyników:

select max(col1) 
     , f_col2
  from (
         select col1
              , f(? ,col2) as f_col2 
           from t
       )
 group
    by f_col2

Ta przepisana instrukcja ma odniesienie tylko do jednego argumentu wiązania, więc teraz DBMS widzi, że wyrażenia w klauzuli GROUP BY i na liście SELECT są identyczne.

HTH

[EDYTUJ]

(Chciałbym, żeby był ładniejszy sposób, dlatego wolę podejście nazwanych argumentów wiązania, których używa Oracle. W przypadku sterownika Perl DBI argumenty pozycyjne są konwertowane na nazwane argumenty w oświadczeniu faktycznie wysyłanym do Oracle.)

Na początku nie widziałem problemu, nie zrozumiałem pierwotnego pytania. (Najwyraźniej kilka innych osób też to przeoczyło.) Ale po przeprowadzeniu kilku przypadków testowych olśniło mnie, na czym polega problem, jakie pytanie działa.

Zobaczę, czy potrafię określić problem:jak uzyskać dwa oddzielne (pozycyjne) argumenty wiązania, które mają być traktowane (przez DBMS) tak, jakby były to dwie referencje do tego samego (nazwanego) argumentu wiązania.

DBMS oczekuje, że wyrażenie w grupie GROUP BY będzie zgodne z wyrażeniem z listy SELECT. Ale te dwa wyrażenia są uważane za RÓŻNE, nawet jeśli wyrażenia są identyczne, gdy jedyną różnicą jest to, że każde wyrażenie odwołuje się do innej zmiennej wiążącej. (Możemy zademonstrować kilka przypadków testowych, które przynajmniej niektóre DBMS pozwolą, ale są bardziej ogólne przypadki, które spowodują wyjątek.)

W tym momencie krótka odpowiedź brzmi:to mnie zakłopotało. Moja sugestia (która może nie być faktyczną odpowiedzią na pierwotne pytanie) polega na zmianie struktury zapytania.

[/EDYTUJ]

Mogę podać więcej szczegółów, jeśli to podejście nie działa lub jeśli masz inny problem z jego znalezieniem. Lub jeśli jest problem z wydajnością (widzę, że optymalizator wybiera inny plan dla przepisanego zapytania, mimo że zwraca określony zestaw wyników. Do dalszych testów naprawdę musielibyśmy wiedzieć, jaki DBMS, jaki sterownik, statystyki itp.)

EDYTUJ (osiem i pół roku później)

Kolejna próba przepisania zapytania. Ponownie, jedynym rozwiązaniem, które wymyśliłem, jest zapytanie z jednym symbolem zastępczym powiązania. Tym razem wstawiamy go do widoku wbudowanego, który zwraca pojedynczy wiersz i łączymy go z t. Widzę, co to robi; Nie jestem pewien, jak optymalizator Oracle to zobaczy. Możemy chcieć (lub potrzebować) dokonać jawnej konwersji, np. TO_NUMBER(?) AS param , TO_DATE(?,'...') AS param , TO_CHAR(?) AS param , w zależności od typu danych parametru bind i typu danych, który chcemy zwrócić z widoku).

Tak zrobiłbym to w MySQL. Pierwotne zapytanie w mojej odpowiedzi wykonuje operację sprzężenia wewnątrz widoku wbudowanego (MySQL tabela pochodna ). I chcemy uniknąć materializacji tabeli pochodnej hughjassa, jeśli możemy tego uniknąć. Z drugiej strony, MySQL prawdopodobnie pozostawiłby oryginalne zapytanie tak długo, jak sql_mode nie zawiera ONLY_FULL_GROUP_BY . MySQL pozwoliłby nam również usunąć FROM DUAL )

  SELECT MAX(t.col1)
       , f( v.param ,t.col2)
    FROM t
   CROSS
    JOIN ( SELECT ? AS param FROM DUAL) v
   GROUP
      BY f( v.param ,t.col2)

Zgodnie z odpowiedzią MadusankaD, w ciągu ostatnich ośmiu lat firma Oracle dodała obsługę ponownego użycia tych samych nazwanych parametrów wiązania w sterowniku JDBC i zachowanie równoważności. (Nie testowałem tego, ale jeśli teraz działa, to świetnie.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak przekazać wartości w anonimowym bloku z parametrem tabeli plsql?

  2. Pomijanie passwd podczas wywoływania sqlplus ze skryptu powłoki

  3. Oracle:różnica między ciągiem NULL i EMPTY

  4. ORA-00910:określona długość jest za długa dla typu danych

  5. Parse SOAP XML w Oracle z przykładem