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

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

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

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
18.05.2010, 18:30
    #36634741
Anton_Demin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сводная таблица (Pivot) в XSLT
...
Рейтинг: 0 / 0
19.05.2010, 10:07
    #36635638
mrxiii
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сводная таблица (Pivot) в XSLT
Anton_Demin, по ссылке речь идёт об обыкновенной плоской группировке.
А вопрос в том, как сделать аналог сводной таблицы Excel, когда одномерный набор данных сворачивается в 2-мерное представление: Помимо построчной группировки, делается ещё и группировка по столбцам (по значениям в поле F4).
...
Рейтинг: 0 / 0
21.05.2010, 13:05
    #36641356
Роман Дынник
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сводная таблица (Pivot) в XSLT
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
21.05.2010, 15:54
    #36641943
mrxiii
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сводная таблица (Pivot) в XSLT
Роман, спасибо, так уже и сделано.

Агрегированные (распределённые по столбцам) данные подготовлены в 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
30.05.2010, 18:56
    #36657868
Pasionario
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сводная таблица (Pivot) в XSLT
Код: 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
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / Сводная таблица (Pivot) в XSLT / 6 сообщений из 6, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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