GROUP BY子句中不允许使用XML方法

时间:2019-01-16 17:03:08

标签: sql sql-server

我正在尝试将“分组依据”添加到我的简单查询XML中。 我在下面的链接中看到了类似的问题,但是我无法用我的问题来弥补。

Link

我的示例代码

DECLARE @xml VARCHAR(8000)  = '<root><que trp=''100001'' ccid=''59748''  /></root>'
DECLARE @recordXml XML = @xml

SELECT
            T.a.value('@trp[1]','CHAR(6)') AS trip_no,
            MAX(T.a.value('@ccid[1]','INT')) AS check_call_id
        FROM @recordXml.nodes('/root/que')T(a)
        WHERE
            LEN(T.a.value('@trp[1]','CHAR(6)')) = 6
            AND ISNUMERIC(T.a.value('@trp[1]','CHAR(6)')) = 1
            AND CONVERT(INT, T.a.value('@trp[1]','CHAR(6)')) > 0
        GROUP BY T.a.value('@trp[1]','CHAR(6)')

感谢您提供任何帮助来解决此问题。

3 个答案:

答案 0 :(得分:3)

使用子查询...

SELECT
    trip_no,
    MAX(check_call_id)   AS check_call_id
FROM
(
    SELECT
        T.a.value('@trp[1]' , 'CHAR(6)') AS trip_no,
        T.a.value('@ccid[1]', 'INT'    ) AS check_call_id
    FROM
        @recordXml.nodes('/root/que')T(a)
    WHERE
        LEN(T.a.value('@trp[1]','CHAR(6)')) = 6
        AND ISNUMERIC(T.a.value('@trp[1]','CHAR(6)')) = 1
        AND CONVERT(INT, T.a.value('@trp[1]','CHAR(6)')) > 0
)
    AS parsed_xml
GROUP BY
    trip_no

答案 1 :(得分:1)

您需要将未聚合的查询包装在CTE或子查询中,然后对其进行聚合。例如:

WITH CTE AS
    (SELECT T.a.value('@trp[1]', 'CHAR(6)') AS trip_no,
            T.a.value('@ccid[1]', 'INT') AS check_call_id
     FROM @recordXml.nodes('/root/que') T(a)
     WHERE LEN(T.a.value('@trp[1]', 'CHAR(6)')) = 6
       AND ISNUMERIC(T.a.value('@trp[1]', 'CHAR(6)')) = 1
       AND CONVERT(int, T.a.value('@trp[1]', 'CHAR(6)')) > 0)
SELECT trip_no,
       MAX(check_call_id)
FROM CTE
GROUP BY trip_no;

另一方面,我建议反对ISNUMERIC,并建议使用TRY_CONVERTISNUMERIC可能有一些奇怪的行为,例如为1返回ISNUMERIC('.'),但为'.'转换为任何数值数据类型将失败。另外,如果ISNUMERIC失败,则以下子句CONVERT(int, T.a.value('@trp[1]', 'CHAR(6)')) > 0将会失败并出错。因此,您可以更加简洁地做到:

WITH CTE AS
    (SELECT T.a.value('@trp[1]', 'CHAR(6)') AS trip_no,
            T.a.value('@ccid[1]', 'INT') AS check_call_id
     FROM @recordXml.nodes('/root/que') T(a)
     WHERE LEN(T.a.value('@trp[1]', 'CHAR(6)')) = 6
       AND TRY_CONVERT(int,T.a.value('@trp[1]', 'CHAR(6)')) > 0) --If this has decimals, use decimal instead of int
SELECT trip_no,
       MAX(check_call_id) AS check_call_id
FROM CTE
GROUP BY trip_no;

答案 2 :(得分:0)

DECLARE @xml VARCHAR(8000)  = '<root><que trp=''100001'' ccid=''59748''  /></root>'
DECLARE @recordXml XML = @xml

SELECT
    dat.trip_no
    , MAX( dat.check_call_id ) AS max_check_call_id
FROM (

    SELECT
        T.a.value( '@trp[1]','CHAR(6)' ) AS trip_no,
        T.a.value( '@ccid[1]','INT' ) AS check_call_id
    FROM @recordXml.nodes( '/root/que' ) T( a )
    WHERE
        LEN( T.a.value('@trp[1]','CHAR(6)') ) = 6
        AND ISNUMERIC( T.a.value( '@trp[1]','CHAR(6)' ) ) = 1
        AND CONVERT( INT, T.a.value( '@trp[1]','CHAR(6)' ) ) > 0

) AS dat
GROUP BY
    dat.trip_no