Почему порядок в XMLAGG не дает того же результата, что и тот же порядок в SELECT?

Почему XMLAGG дает мне другой порядок, чем мой запрос, хотя у них одинаковый ORDER BY?

Я не могу понять, как получить мой XML в том же порядке, что и мой запрос. Я пробовал использовать CONVERT(file_name, 'US7ASCII') вместе с LOWER, чтобы игнорировать акцентированные символы и прописные буквы, что сделало его лучше, но все равно это другое.
Я тоже пытался использовать COLLATE, но, возможно, я просто не понимаю, как это работает и как его использовать, потому что оно абсолютно ничего не дало.

Так что же мне не хватает? Как я могу заставить XMLAGG дать мне тот же результат, что и запрос?

Базовый запрос (без XMLAGG):

В идеале я бы предпочел не изменять этот запрос, если только нет способа сгенерировать XML в том же порядке.

SELECT id, file_name
  FROM test_files
 ORDER BY file_name;

Результат:

ИДЕНТИФИКАТОР Имя файла 1 docx-01.docx 2 Docx-02.docx 3 docx-03.docx 4 документ-01.doc 5 Док-02.doc 6 документ-03.doc 7 Э .ppt 8 электронная .ppt 9 Э .ppt 10 é .ppt 11 !é.ppt 12 _é.ppt 13 Э.ппт 14 e.ppt 15 Э.ppt 16 é.ppt 17 e0.ppt 18 é0.ppt 19 pdf-01.pdf 20 pdf-02.pdf 21 pdf-03.pdf 22 !.ppt 23 _.ppt 24 ppt-e .ppt 25 ppt-é .ppt 26 ppt-e.ppt 27 ppt-é.ppt 28 ppt-e0.ppt 29 ppt-é0.ppt 30 ppt-01.ppt 31 !0.ppt 32 _0.ppt

Запрос на создание XML (с XMLAGG):

ПРИМЕЧАНИЕ. Это касается CONVERT и LOWER, которые наиболее близки к желаемому результату.

SELECT XMLELEMENT("files",
                  XMLAGG(XMLELEMENT("file",
                                    XMLFOREST(id AS "id",
                                              file_name AS "file_name"))
                         ORDER BY LOWER(CONVERT(file_name, 'US7ASCII'))))
  FROM test_files;

Результат:

<files>
  <file><id>22</id><file_name>!.ppt</file_name></file>
  <file><id>31</id><file_name>!0.ppt</file_name></file>
  <file><id>11</id><file_name>!é.ppt</file_name></file>
  <file><id>23</id><file_name>_.ppt</file_name></file>
  <file><id>32</id><file_name>_0.ppt</file_name></file>
  <file><id>12</id><file_name>_é.ppt</file_name></file>
  <file><id>4</id> <file_name>doc-01.doc</file_name></file>
  <file><id>5</id> <file_name>Doc-02.doc</file_name></file>
  <file><id>6</id> <file_name>doc-03.doc</file_name></file>
  <file><id>1</id> <file_name>docx-01.docx</file_name></file>
  <file><id>2</id> <file_name>Docx-02.docx</file_name></file>
  <file><id>3</id> <file_name>docx-03.docx</file_name></file>
  <file><id>7</id> <file_name>E .ppt</file_name></file>
  <file><id>8</id> <file_name>e .ppt</file_name></file>
  <file><id>9</id> <file_name>É .ppt</file_name></file>
  <file><id>10</id><file_name>é .ppt</file_name></file>
  <file><id>13</id><file_name>E.ppt</file_name></file>
  <file><id>14</id><file_name>e.ppt</file_name></file>
  <file><id>15</id><file_name>É.ppt</file_name></file>
  <file><id>16</id><file_name>é.ppt</file_name></file>
  <file><id>17</id><file_name>e0.ppt</file_name></file>
  <file><id>18</id><file_name>é0.ppt</file_name></file>
  <file><id>19</id><file_name>pdf-01.pdf</file_name></file>
  <file><id>20</id><file_name>pdf-02.pdf</file_name></file>
  <file><id>21</id><file_name>pdf-03.pdf</file_name></file>
  <file><id>30</id><file_name>ppt-01.ppt</file_name></file>
  <file><id>24</id><file_name>ppt-e .ppt</file_name></file>
  <file><id>25</id><file_name>ppt-é .ppt</file_name></file>
  <file><id>26</id><file_name>ppt-e.ppt</file_name></file>
  <file><id>27</id><file_name>ppt-é.ppt</file_name></file>
  <file><id>28</id><file_name>ppt-e0.ppt</file_name></file>
  <file><id>29</id><file_name>ppt-é0.ppt</file_name></file>
</files>

Обновлять

Мне удалось заставить мой базовый запрос дать мне тот же порядок, что и запрос XML, добавив COLLATE binary_ai в предложение order by. Однако я бы все же предпочел не вносить никаких изменений в мой основной запрос.

Я также был бы признателен за объяснение того, почему ORDER BY внутри XMLAGG не ведет себя так же, как при запросе.

🤔 А знаете ли вы, что...
SQL имеет стандарт ANSI SQL, который определяет базовый синтаксис для всех реляционных баз данных.


2
50
1

Ответ:

Решено

Судя по порядку, в котором отображаются результаты вашего исходного запроса, для NLS_SORT и NLS_COMP установлено значение BINARY по умолчанию, а для NLS_LANGUAGE установлено значение французского (спасибо за упоминание вашего языка в вашем профиле!).

Похоже, что предложение order by в XMLAGG не учитывает настройки NLS.

Вместо того, чтобы пытаться манипулировать значениями вручную для упорядочения, вы можете использовать функцию NLSSORT:

XMLAGG(... ORDER BY NLSSORT(file_name, 'NLS_SORT=XFRENCH'))

Используя это и добавив XMLSERIALIZE только для форматирования для удобства чтения, вы получите:

SELECT XMLSERIALIZE(DOCUMENT XMLELEMENT("files",
                  XMLAGG(XMLELEMENT("file",
                                    XMLFOREST(id AS "id",
                                              file_name AS "file_name"))
                         ORDER BY NLSSORT(file_name, 'NLS_SORT=XFRENCH'))) INDENT SIZE = 2)
  FROM test_files;
XML <файлы>
  <файл>
    <id>1</id>
    <имя_файла>docx-01.docx</имя_файла>
  </file>
  <file>
    <id>2 </id>
    <имя_файла >Docx-02.docx</имя_файла>
  </file>
  <file>
    <id>3</id>
    <имя_файла>docx-03.docx</имя_файла>
  </file>
  <файл>
    <id>4</id>
    <имя_файла>doc-01.doc</имя_файла>
  </file>
  <файл>
    <id>5</id>
    <имя_файла>Doc-02.doc< /file_name>
  </file>
  <file>
    <id>6</id>
    <file_name>doc-03.doc</file_name>
  </file>
  <file>
    <id>7</ id>
    <file_name>E .ppt</file_name>
  </file>
  <file>
    <id>8</id>
    <file_name>e .ppt</file_name>
  </file>
  <файл >_ имя_файла>é .ppt</имя_файла>
  </file>
  <file>
    <id>11</id>
    <file_name>!é.ppt</file_name>
  </file>
  <file>
    <id>12</id>
    < file_name>_é.ppt</file_name>
  </file>
  <file>
    <id>13</id>
    <file_name>E.ppt</file_name>
  </file>
  <file>
    <id >14</id>
    <file_name>e.ppt</file_name>
  </file>
  <file>
    <id>15</id>
    <file_name>É.ppt</file_name>
  </файл >
  <файл>
    <id>16</id>
    <file_name>é.ppt</file_name>
  </file>
  <file>
    <id>17</id>
    <имя_файла>e0.ppt </file_name>
  </file>
  <file>
    <id>18</id>
    <file_name>é0.ppt</file_name>
  </file>
  <file>
    <id>19</id >
    <имя_файла>pdf-01.pdf</имя_файла>
  </file>
  <файл>
    <id>20</id>
    <имя_файла>pdf-02.pdf</имя_файла>
  </файл>
  <файл>
    <id>21</id>
    <имя_файла>pdf-03.pdf</file_name>
  </file>
  <file>
    <id>22</id>
    <имя_файла>!. ppt</file_name>
  </file>
  <file>
    <id>23</id>
    <file_name>_.ppt</file_name>
  </file>
  <file>
    <id>24</ id>
    <file_name>ppt-e .ppt</file_name>
  </file>
  <file>
    <id>25</id>
    <file_name>ppt-é .ppt</file_name>
  </файл >
  <файл>
    <id>26</id>
    <file_name>ppt-e.ppt</file_name>
  </file>
  <file>
    <id>27</id>
    <имя_файла>ppt -é.ppt</file_name>
  </file>
  <file>
    <id>28</id>
    <file_name>ppt-e0.ppt</file_name>
  </file>
  <file>
    < id>29</id>
    <file_name>ppt-é0.ppt</file_name>
  </file>
  <file>
    <id>30</id>
    <file_name>ppt-01.ppt</ имя_файла >
  </file>
  <file>
    <id>31</id>
    <file_name>!0.ppt</file_name>
  </file>
  <file>
    <id>32</id>
<file_name>_0.ppt</file_name>
  </file>
</files>

рабочий пример


Вы также можете упорядочить результаты запроса перед агрегированием:

SELECT XMLSERIALIZE(DOCUMENT XMLELEMENT("files",
                  XMLAGG(XMLELEMENT("file",
                                    XMLFOREST(id AS "id",
                                              file_name AS "file_name"))
                         )) INDENT SIZE = 2)
  FROM test_files
  ORDER BY file_name;

рабочий пример

... который Oracle рекомендует в примечании о поддержке 1407946.1; но я не знаю, действительно ли гарантирован порядок элементов, если вы это сделаете. Возможно, это так, но я могу представить себе будущие изменения в оптимизаторе или, может быть, просто параллельный запрос, который на него повлияет.