【问题标题】:XQuery for selecting and grouping用于选择和分组的 XQuery
【发布时间】:2020-07-30 19:06:06
【问题描述】:

我正在尝试从 xml 列中导出一些信息。

应用逻辑: 在每个部分中,演员姓名可能会出现两次。 (演员 + 歌曲)产生独特的组合。

仅在聚合级别、场景 = 1 时保留。我们不关心场景=2。 我们关心特定演员的台词。 辛巴、木法沙和扎祖。 让我们不要担心疤痕。他很卑鄙。 我的预期输出是:

output

到目前为止我的 T-Sql 代码: 我已经设法过滤掉聚合级别 = 2。

有人可以帮忙吗?

DECLARE @Temp AS TABLE (Information xml)
INSERT INTO @Temp SELECT @x;
WITH XMLNAMESPACES ('lyceum' AS ns1)
SELECT
    Z.query('ns1:feature')
FROM @Temp
CROSS APPLY Information.nodes('/ns1:report/ns1:detail/ns1:parts/ns1:part') AS Y(Z)
WHERE Z.exist('ns1:aggregation[.="1"]') = 1

您可以在下面找到 xml,以便轻松重现:

DECLARE @x as xml;
set @x = '<ns1:report xmlns:ns1="lyceum">
    <ns1:header>
        <ns1:report>The Lion King</ns1:report>
    </ns1:header>
    <ns1:detail>
        <ns1:parts>
            <ns1:part>
                <ns1:aggregation>
                    <ns1:scene>1</ns1:scene>
                </ns1:aggregation>
                <ns1:feature>
                    <ns1:actor>Simba</ns1:actor>
                    <ns1:lines>100</ns1:lines>
                    <ns1:song>1</ns1:song>
                </ns1:feature>
                <ns1:feature>
                    <ns1:actor>Mufasa</ns1:actor>
                    <ns1:lines>200</ns1:lines>
                    <ns1:song>1</ns1:song>
                </ns1:feature>
                <ns1:feature>
                    <ns1:actor>Simba</ns1:actor>
                    <ns1:lines>300</ns1:lines>
                    <ns1:song>2</ns1:song>
                </ns1:feature>
                <ns1:feature>
                    <ns1:actor>Zazu</ns1:actor>
                    <ns1:lines>400</ns1:lines>
                    <ns1:song>2</ns1:song>
                </ns1:feature>
                <ns1:feature>
                    <ns1:actor>Scar</ns1:actor>
                    <ns1:lines>500</ns1:lines>
                    <ns1:song>2</ns1:song>
                </ns1:feature>
            </ns1:part>
            <ns1:part>
                <ns1:aggregation>
                    <ns1:scene>2</ns1:scene>
                </ns1:aggregation>
                <ns1:feature>
                    <ns1:actor>Simba</ns1:actor>
                    <ns1:lines>600</ns1:lines>
                    <ns1:song>1</ns1:song>
                </ns1:feature>
                <ns1:feature>
                    <ns1:actor>Mufasa</ns1:actor>
                    <ns1:lines>700</ns1:lines>
                    <ns1:song>1</ns1:song>
                </ns1:feature>
                <ns1:feature>
                    <ns1:actor>Simba</ns1:actor>
                    <ns1:lines>800</ns1:lines>
                    <ns1:song>2</ns1:song>
                </ns1:feature>
                <ns1:feature>
                    <ns1:actor>Zazu</ns1:actor>
                    <ns1:lines>900</ns1:lines>
                    <ns1:song>2</ns1:song>
                </ns1:feature>
                <ns1:feature>
                    <ns1:actor>Scar</ns1:actor>
                    <ns1:lines>1000</ns1:lines>
                    <ns1:song>2</ns1:song>
                </ns1:feature>
            </ns1:part>
        </ns1:parts>
    </ns1:detail>
</ns1:report>'

【问题讨论】:

    标签: sql-server tsql xquery-sql


    【解决方案1】:

    您要求 XQuery 进行选择和分组:试试这个:

    模拟您的问题的样机表

    DECLARE @Temp AS TABLE (Information xml);
    INSERT @Temp VALUES
    ('<ns1:report xmlns:ns1="lyceum">
        <ns1:header>
            <ns1:report>The Lion King</ns1:report>
        </ns1:header>
        <ns1:detail>
            <ns1:parts>
                <ns1:part>
                    <ns1:aggregation>
                        <ns1:scene>1</ns1:scene>
                    </ns1:aggregation>
                    <ns1:feature>
                        <ns1:actor>Simba</ns1:actor>
                        <ns1:lines>100</ns1:lines>
                        <ns1:song>1</ns1:song>
                    </ns1:feature>
                    <ns1:feature>
                        <ns1:actor>Mufasa</ns1:actor>
                        <ns1:lines>200</ns1:lines>
                        <ns1:song>1</ns1:song>
                    </ns1:feature>
                    <ns1:feature>
                        <ns1:actor>Simba</ns1:actor>
                        <ns1:lines>300</ns1:lines>
                        <ns1:song>2</ns1:song>
                    </ns1:feature>
                    <ns1:feature>
                        <ns1:actor>Zazu</ns1:actor>
                        <ns1:lines>400</ns1:lines>
                        <ns1:song>2</ns1:song>
                    </ns1:feature>
                    <ns1:feature>
                        <ns1:actor>Scar</ns1:actor>
                        <ns1:lines>500</ns1:lines>
                        <ns1:song>2</ns1:song>
                    </ns1:feature>
                </ns1:part>
                <ns1:part>
                    <ns1:aggregation>
                        <ns1:scene>2</ns1:scene>
                    </ns1:aggregation>
                    <ns1:feature>
    <!-- shortened for brevity -->
                    </ns1:feature>
                </ns1:part>
            </ns1:parts>
        </ns1:detail>
    </ns1:report>');
    

    --查询

    WITH XMLNAMESPACES('lyceum' AS ns1)
    SELECT p.query('<root>
                    {
                        for $s in distinct-values(ns1:feature/ns1:song/text())
                        return <song scene="{$s}">
                            {
                            for $f in ns1:feature[ns1:song[text()=$s]]
                            return
                            if($f/ns1:actor/text() != "Scar") then
                                <actor name="{$f/ns1:actor/text()}" lines="{$f/ns1:lines/text()}"/>
                            else
                                ()
                            }
                        </song>
                    }
                    </root>')
      
    FROM @Temp t
    CROSS APPLY t.Information.nodes('/ns1:report/ns1:detail/ns1:parts/ns1:part[(ns1:aggregation/ns1:scene/text())[1]="1"]') A(p);
    

    结果

    <root>
      <song scene="1">
        <actor name="Simba" lines="100" />
        <actor name="Mufasa" lines="200" />
      </song>
      <song scene="2">
        <actor name="Simba" lines="300" />
        <actor name="Zazu" lines="400" />
      </song>
    </root>
    

    简而言之:

    • 我们使用.nodes() 中的谓词返回&lt;scene&gt;=1 的部分
    • 我们使用.query()返回一个新创建的XML
    • 我们添加(可能会省略)&lt;root&gt; 节点
    • 我们添加了一个 FLWOR 查询,该查询通过不同的歌曲 ID 列表运行
    • 我们在另一个 FLOWR 查询中使用此歌曲 ID 作为谓词来过滤适合的 &lt;feature&gt; 元素
    • 我们检查演员的名字不是“Scar”

    您要求的输出是一个完全不同的问题。 使用 content 作为列名要求预先知道所有预期的名称(PIVOT条件聚合)或使用动态创建的语句。

    【讨论】:

    • 谢谢@Shnugo。您对我的问题的预期输出是正确的。这确实是一个不同的问题。
    猜你喜欢
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多