Действительно ли возможно использовать GROUP BY с, связывают переменные?

В качестве своего рода теоретического дополнения к предыдущим ответам я хотел бы отметить, что «магическое» значение ± 308 происходит непосредственно из двоичного представления чисел с плавающей точкой. Число с плавающей запятой двойной точности имеет форму ± c * 2 ** q с «малым» дробным значением c (~ 1), а q - целое число, записанное с 11 двоичными цифрами (включая 1 бит для знака) , Тот факт, что 2 ** (2 ** 10-1) имеет 308 (десятичных) цифр, объясняет появление 10 ** ± 308 в крайних значениях с плавающей запятой.

Расчет в Python:

>>> print len(repr(2**(2**10-1)).rstrip('L'))
308

6
задан Apocalisp 2 June 2009 в 18:06
поделиться

3 ответа

Я предлагаю переписать оператор так, чтобы был только один аргумент привязки. Этот подход уродлив, но возвращает набор результатов:

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

Этот переписанный оператор имеет ссылку только на один аргумент связывания, поэтому теперь СУБД видит, что выражения в предложении GROUP BY и списке SELECT идентичны.

HTH

[EDIT]

(Хотелось бы, чтобы был более красивый способ, поэтому я предпочитаю подход с именованным аргументом связывания, который использует Oracle. С драйвером Perl DBI позиционные аргументы преобразуются в именованные аргументы в фактически отправленном операторе в Oracle.)

Сначала я не заметил проблемы, я не понял исходного вопроса. (По-видимому, несколько других людей тоже это пропустили.) Но после выполнения некоторых тестовых примеров меня осенило, в чем проблема, какой вопрос был решающим.

Дайте мне посмотреть, могу ли я сформулировать проблему: как получить два отдельные (позиционные) аргументы связывания, которые должны обрабатываться (СУБД), как если бы это были две ссылки на один и тот же (именованный) аргумент связывания.

СУБД ожидает, что выражение в GROUP BY будет соответствовать выражению в списке SELECT . Но эти два выражения считаются РАЗЛИЧНЫМИ, даже если выражения идентичны, когда единственное различие состоит в том, что каждое выражение ссылается на другую переменную связывания. (Мы можем продемонстрировать некоторые тестовые примеры, которые допускаются по крайней мере некоторые СУБД, но есть и более общие случаи, которые вызывают исключение.)

Здесь краткий ответ: это меня озадачило. У меня есть предложение (которое, возможно, не является действительным ответом на исходный вопрос) - изменить структуру запроса.

[/ EDIT]

Я могу предоставить более подробную информацию, если этот подход не работает, или если у вас есть другие проблемы с его выяснением. Или если есть проблема с производительностью (я вижу, как оптимизатор выбирает другой план для переписанного запроса, даже если он возвращает указанный набор результатов. Для дальнейшего тестирования нам действительно нужно знать, какая СУБД, какой драйвер, статистика и т.д.)

РЕДАКТИРОВАТЬ (восемь с половиной лет спустя)

Еще одна попытка переписать запрос. Опять же, единственное решение, которое я придумал, - это запрос с одним заполнителем привязки. На этот раз мы вставляем его во встроенное представление, которое возвращает одну строку, и присоединяем ее к t. Я вижу, что он делает; Я не уверен, как оптимизатор Oracle это увидит. Возможно, нам потребуется (или потребуется) выполнить явное преобразование, например TO_NUMBER (?) AS param , TO_DATE (?, '...') AS param , TO_CHAR (?) AS param , в зависимости от типа данных параметра привязки и типа данных, который мы хотим вернуть как с точки зрения.)

Вот как я бы сделал это в MySQL. Исходный запрос в моем ответе выполняет операцию соединения внутри встроенного представления (производная таблица MySQL ). И мы хотим избежать материализации производной таблицы от hughjass, если мы можем этого избежать. С другой стороны, MySQL, вероятно, позволит исходному запросу скользить, пока sql_mode не включает ONLY_FULL_GROUP_BY . MySQL также позволил бы нам отказаться от 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)

Согласно ответу MadusankaD, за последние восемь лет Oracle добавила поддержку повторного использования параметров привязки с одинаковыми именами в драйвере JDBC и сохранения эквивалентность.

8
ответ дан 10 December 2019 в 00:43
поделиться

Вы пытались использовать ? вместо именованных переменных связывания? А какой драйвер вы используете? Я попробовал этот тривиальный пример, используя тонкий драйвер, и он, похоже, работал нормально:

PreparedStatement ps = con.prepareStatement("SELECT COUNT(*), TO_CHAR(SYSDATE, ?) FROM DUAL GROUP BY TO_CHAR(SYSDATE, ?)");
ps.setString(1, "YYYY");
ps.setString(2, "YYYY");
ps.executeQuery();
0
ответ дан 10 December 2019 в 00:43
поделиться

Во втором случае на самом деле есть две переменные - вам нужно будет отправить их обе с одинаковым значением.

0
ответ дан 10 December 2019 в 00:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: