将PostgreSQL string_agg移植到SQL Server,ORDER BY出现问题

say*_*yap 5 sql-server postgresql aggregate sql-order-by

在PostgreSQL中,有一个非常有用的string_agg函数,允许查询如下:

SELECT
    contacts.first_name,
    contacts.last_name,
    (
        SELECT
            string_agg(number, ', ' ORDER BY phones.priority)
        FROM
            phones
        WHERE
            phones.contact_id = contacts.id
    ) AS phone_numbers
FROM
    contacts
Run Code Online (Sandbox Code Playgroud)

同样,这可以使用group_concat在MySQL中完成.

现在,我试图将其作为CLR用户定义的聚合端口导入SQL Server.代码本身不是问题,因为在整个网络上有成千上万的例子来创建这个特定的聚合(这就是问题:为什么它不是SQL Server的一部分?).

问题是,我找不到一种干净的方式来应用ORDER BY,因为SQL Server不仅不支持聚合函数中的ORDER BY,它还禁止在子查询中使用ORDER BY.我最好的选择是:

SELECT
    contacts.first_name,
    contacts.last_name,
    (
        SELECT
            dbo.string_agg(number, ', ')
        FROM
            (
                SELECT TOP <some really large number>
                    number
                FROM
                    phones
                WHERE
                    phones.contact_id = contacts.id
                ORDER BY
                    phones.priority
            ) AS phones
    ) AS phone_numbers
FROM
    contacts
Run Code Online (Sandbox Code Playgroud)

有更好的解决方法吗?是的,我已经阅读了子查询中允许的order by子句,我敢说,这是子查询中ORDER BY的有效用例.

say*_*yap 0

看起来没有比使用子查询更好的选择TOP <some really large number>来绕过 SQL Server 的限制:

SELECT
    contacts.first_name,
    contacts.last_name,
    (
        SELECT
            dbo.string_agg(number, ', ')
        FROM
            (
                SELECT TOP <some really large number>
                    number
                FROM
                    phones
                WHERE
                    phones.contact_id = contacts.id
                ORDER BY
                    phones.priority
            ) AS phones
    ) AS phone_numbers
FROM
    contacts
Run Code Online (Sandbox Code Playgroud)