powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / Сводная таблица (Pivot) в XSLT
6 сообщений из 6, страница 1 из 1
Сводная таблица (Pivot) в XSLT
    #36634722
mrxiii
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет,

Подозреваю, что должна быть возможность, но не знаю, как сделать следующее.

Есть входной набор данных такого вида:

F1F2F3F4F5F6Центральный1Тульская область10120Центральный2Москва5,5140Центральный2Москва10130Южный1Краснодарский край8,5150Приволжский1Удмуртская Республика102120Уральский1Ханты-Мансийский А.О.5,5290Уральский2Челябинская область5,53150Уральский2Челябинская область77500Уральский2Челябинская область11,5160Уральский2Челябинская область134200Дальневосточный1Республика Саха (Якутия)132130
XML этих данных:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
<DATA>
<DataSet>
<DATASET_ROW><F1>Центральный</F1><F2> 1 </F2><F3>Тульская область</F3><F4> 10 </F4><F5> 1 </F5><F6> 20 </F6></DATASET_ROW>
<DATASET_ROW><F1>Центральный</F1><F2> 2 </F2><F3>Москва</F3><F4> 5 , 5 </F4><F5> 1 </F5><F6> 40 </F6></DATASET_ROW>
<DATASET_ROW><F1>Центральный</F1><F2> 2 </F2><F3>Москва</F3><F4> 10 </F4><F5> 1 </F5><F6> 30 </F6></DATASET_ROW>
<DATASET_ROW><F1>Южный</F1><F2> 1 </F2><F3>Краснодарский край</F3><F4> 8 , 5 </F4><F5> 1 </F5><F6> 50 </F6></DATASET_ROW>
<DATASET_ROW><F1>Приволжский</F1><F2> 1 </F2><F3>Удмуртская Республика</F3><F4> 10 </F4><F5> 2 </F5><F6> 120 </F6></DATASET_ROW>
<DATASET_ROW><F1>Уральский</F1><F2> 1 </F2><F3>Ханты-Мансийский А.О.</F3><F4> 5 , 5 </F4><F5> 2 </F5><F6> 90 </F6></DATASET_ROW>
<DATASET_ROW><F1>Уральский</F1><F2> 2 </F2><F3>Челябинская область</F3><F4> 5 , 5 </F4><F5> 3 </F5><F6> 150 </F6></DATASET_ROW>
<DATASET_ROW><F1>Уральский</F1><F2> 2 </F2><F3>Челябинская область</F3><F4> 7 </F4><F5> 7 </F5><F6> 500 </F6></DATASET_ROW>
<DATASET_ROW><F1>Уральский</F1><F2> 2 </F2><F3>Челябинская область</F3><F4> 11 , 5 </F4><F5> 1 </F5><F6> 60 </F6></DATASET_ROW>
<DATASET_ROW><F1>Уральский</F1><F2> 2 </F2><F3>Челябинская область</F3><F4> 13 </F4><F5> 4 </F5><F6> 200 </F6></DATASET_ROW>
<DATASET_ROW><F1>Дальневосточный</F1><F2> 1 </F2><F3>Республика Саха (Якутия)</F3><F4> 13 </F4><F5> 2 </F5><F6> 130 </F6></DATASET_ROW>
</DataSet>
</DATA>

Требуется сложить эти данные в сводную таблицу со структурой, представленной на скриншоте.

Кто может подсказать, реализуемо ли это и если да, то как?
...
Рейтинг: 0 / 0
Сводная таблица (Pivot) в XSLT
    #36634741
Фотография Anton_Demin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Сводная таблица (Pivot) в XSLT
    #36635638
mrxiii
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anton_Demin, по ссылке речь идёт об обыкновенной плоской группировке.
А вопрос в том, как сделать аналог сводной таблицы Excel, когда одномерный набор данных сворачивается в 2-мерное представление: Помимо построчной группировки, делается ещё и группировка по столбцам (по значениям в поле F4).
...
Рейтинг: 0 / 0
Сводная таблица (Pivot) в XSLT
    #36641356
Фотография Роман Дынник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mrxiiiAnton_Demin, по ссылке речь идёт об обыкновенной плоской группировке.
А вопрос в том, как сделать аналог сводной таблицы Excel, когда одномерный набор данных сворачивается в 2-мерное представление: Помимо построчной группировки, делается ещё и группировка по столбцам (по значениям в поле F4).

Сгруппируйте также F4 (вложенный for-each-group).
что то на подобие этого:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
  <xsl:for-each-group select="DATA/DATASET/DATASET_ROW" group-by="F1">
    <xsl:for-each select="current-group()">
      <xsl:variable name="$f1" select="." />
      <tr>
         <td><xsl:value-of select="."/></td>
         <xsl:for-each-group select="//DATA/DATASET/DATASET_ROW" group-by="F4">
              <xsl:for-each select="current-group()">
                <td><xsl:value-of select="."/></td>
              </xsl:for-each>
         </xsl:for-each-group>
      </tr>
      ...
  </xsl:for-each>
 </xsl:for-each-group>

А вообще правильнее и проще посчитать/сгруппировать все на стороне сервера (sql-запросами)
и вернуть dataset состоящий из нескольких таблиц, содержаних тоталы, уникальные группы и т.п.
И уже это все раскладывать с помощью xslt. При этом xslt будет гораздо проще и без всяких группировок, которые кстати только в xslt 2.0 поддерживаются по-моему.
...
Рейтинг: 0 / 0
Сводная таблица (Pivot) в XSLT
    #36641943
mrxiii
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Роман, спасибо, так уже и сделано.

Агрегированные (распределённые по столбцам) данные подготовлены в SQL с помощью группировок и выгружены из SQL в XML/XSLT конструкциями вида:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
XmlElement( "PIVOT_DATA"
           , xmlagg( XmlConcat( XmlElement( "Cell"
                                          , XMLAttributes('subsum-num-2' as "StyleID")
                                          , case
                                            when DATA.Value <>  0 
                                            then XmlElement("Data"
                                                           , XMLAttributes('Number' as "Type")
                                                           , trim(to_char(DATA.Value, '999999999999999.99')))
                                            end
                                          )
                              , XmlElement( "Cell"
                                          , XMLAttributes('subsum-num-0' as "StyleID")
                                          , case
                                            when DATA.CNT <>  0 
                                            then XmlElement("Data"
                                                           , XMLAttributes('Number' as "Type")
                                                           , trim(to_char(DATA.CNT, '999999999999999')))
                                            end
                                          )
                              )
                     order by DATA_MATRIX.COLUMN_NUMBER
                   )).Getclobval()

(с элементами xml-таблиц Excel)

Далее блоки XML (например, описание агрегированных данных) выводятся в результирующий файл отчета, а блоки XSLT (например, описания форматирования столбцов с неизвестным заранее их количеством) вставляются в XSLT-код с добавлением необходимых ns-префиксов (т.к. возникали проблемы с недопустимыми двоеточиями при получении набора данных в Oracle BI Publisher) примерно так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
<xsl:template match="PIVOT_DATA" name="PIVOT_DATA_TEMPLATE">
	<xsl:for-each select="child::*">
		<xsl:element name="{name()}">
			<xsl:for-each select="@*">
				<xsl:attribute name="ss:{name()}"><xsl:value-of select="."/><xsl:apply-templates/></xsl:attribute>
			</xsl:for-each>
			<xsl:if test="name()='Data'">
				<xsl:value-of select="."/>
			</xsl:if>
			<xsl:call-template name="PIVOT_DATA_TEMPLATE"/>
		</xsl:element>
	</xsl:for-each>
</xsl:template>

Наверняка, есть способ обойтись без генерации XML в SQL, а использовать только возможности XSLT, но пока такого решения не найдено.
...
Рейтинг: 0 / 0
Сводная таблица (Pivot) в XSLT
    #36657868
Pasionario
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:output method="html" indent="yes"/>
  
  <xsl:key name="f1" match="DATASET_ROW" use="F1"/>
  <xsl:key name="f3" match="DATASET_ROW" use="F3"/>
  <xsl:key name="f4" match="DATASET_ROW" use="F4"/>

  <xsl:variable name="x" select="//DATASET_ROW[generate-id(.) = generate-id(key('f4', F4))]"/>

  <xsl:template match="//DATA/DataSet">
    <table border="box">
      <tr>
        <th rowspan="2">No</th>
        <th rowspan="2">Регион</th>
        <th rowspan="2">Руб.</th>
        <th rowspan="2">Шт.</th>
        <xsl:for-each select="$x">
          <xsl:sort select="translate(F4, ',', '.')" data-type="number"/>
          <th colspan="2">
            <xsl:value-of select="format-number(translate(F4, ',', '.'), '#.00')"/>
          </th>
        </xsl:for-each>
      </tr>
      <tr>
        <xsl:for-each select="$x">
          <xsl:sort select="translate(F4, ',', '.')" data-type="number"/>
          <td>руб</td>
          <td>шт</td>
        </xsl:for-each>
      </tr>
      <xsl:apply-templates select="DATASET_ROW[generate-id(.) = generate-id(key('f1', F1))]"/>
      <tr>
        <th colspan="2">Итого</th>
        <td>
          <xsl:value-of select="sum(DATASET_ROW/F6)"/>
        </td>
        <td>
          <xsl:value-of select="sum(DATASET_ROW/F5)"/>
        </td>
        <xsl:for-each select="$x">
          <xsl:sort select="translate(F4, ',', '.')" data-type="number"/>
          <th>
            <xsl:value-of select="sum(key('f4', F4)/F6)"/>
          </th>
          <th>
            <xsl:value-of select="sum(key('f4', F4)/F5)"/>
          </th>
        </xsl:for-each>
      </tr>
    </table>
  </xsl:template>

  <xsl:template match="DATASET_ROW">
    <xsl:variable name="F1" select="F1"/>
    
    <tr>
      <th colspan="2">
        <xsl:value-of select="F1"/>
      </th>
      <th>
        <xsl:value-of select="sum(key('f1', F1)/F6)"/>
      </th>
      <th>
        <xsl:value-of select="sum(key('f1', F1)/F5)"/>
      </th>
      <xsl:for-each select="$x">
        <xsl:sort select="translate(F4, ',', '.')" data-type="number"/>
        <xsl:variable name="y" select="F4"/>
        <th> 
          <xsl:if test="sum(key('f1', $F1)[F4 = $y]/F6) != 0">
            <xsl:value-of select="sum(key('f1', $F1)[F4 = $y]/F6)"/>
          </xsl:if>
        </th>
        <th>
           
          <xsl:if test="sum(key('f1', $F1)[F4 = $y]/F6) != 0">
            <xsl:value-of select="sum(key('f1', $F1)[F4 = $y]/F5)"/>
          </xsl:if>
        </th>
      </xsl:for-each>
    </tr>
    <tr>
      <xsl:for-each select="key('f1', F1)[generate-id(.) = generate-id(key('f3', F3))]">
        <xsl:variable name="F3" select="F3"/>
        <tr>
          <td>
            <xsl:number value="position()"/>
          </td>
          <td>
            <xsl:value-of select="F3"/>
          </td>
          <td>
            <xsl:value-of select="sum(key('f3', F3)/F6)"/>
          </td>
          <td>
            <xsl:value-of select="sum(key('f3', F3)/F5)"/>
          </td>

          <xsl:for-each select="$x">
            <xsl:sort select="translate(F4, ',', '.')" data-type="number"/>
            <xsl:variable name="y" select="F4"/>
            <th>
               
              <xsl:if test="sum(key('f3', $F3)[F4 = $y]/F6) != 0">
                <xsl:value-of select="sum(key('f3', $F3)[F4 = $y]/F6)"/>
              </xsl:if>
            </th>
            <th>
               
              <xsl:if test="sum(key('f3', $F3)[F4 = $y]/F6) != 0">
                <xsl:value-of select="sum(key('f3', $F3)[F4 = $y]/F5)"/>
              </xsl:if>
            </th>
          </xsl:for-each>
          
        </tr>
      </xsl:for-each>
    </tr>
  </xsl:template>
  
</xsl:stylesheet>
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / Сводная таблица (Pivot) в XSLT
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]