【问题标题】:how to make a DISTINCT of STRING_AGG如何制作 STRING_AGG 的 DISTINCT
【发布时间】:2021-12-26 21:46:06
【问题描述】:

我正在尝试对 STRING_AGG 函数的 offerDetails 列进行 DISTINCT

OUTER APPLY
(
    SELECT 
        STRING_AGG(CAST(co.OfferId AS NVARCHAR(MAX)), ';') AS OfferDetails, 
        STRING_AGG(CAST(ct.ConferenceId AS NVARCHAR(MAX)), ';') AS CustomTransferDetails
    FROM ConferenceTransfer ct
    INNER JOIN ConferenceOffer co ON ct.ConferenceId = co.ConferenceId
    WHERE
        ct.ConferenceTransferTypeId = 1 AND
        ct.DateStarted IS NOT NULL AND
        ct.CallerUserId = @agentId AND
        ct.DateInitiated BETWEEN @dateFrom AND @dateTo
) CallTransfered

【问题讨论】:

  • 修复架构!如果您在单个列中分隔数据,您应该将您的架构视为BROKEN。这是一个有缺陷的设计,需要额外的桌子。纠正他损坏的设计,突然间这个查询(可能还有其他查询)会更加简单。

标签: sql sql-server distinct


【解决方案1】:

我不知道任何使 string_agg 不同的本机方式,但您可以通过使用子查询和 row_number 来识别第一个实例,即忽略每个值的第一个实例,即

OUTER APPLY
(
    SELECT 
        STRING_AGG(CAST(CASE WHEN c.RowNumber = 1 THEN c.OfferId END AS NVARCHAR(MAX)), ';') AS OfferDetails, 
        STRING_AGG(CAST(c.ConferenceId AS NVARCHAR(MAX)), ';') AS CustomTransferDetails
    FROM (  SELECT  co.OfferId,
                    ct.ConferenceId,
                    RowNumber = ROW_NUMBER() OVER(PARTITION BY co.OfferId ORDER BY ct.ConferenceId)
            FROM    ConferenceTransfer ct
                    INNER JOIN ConferenceOffer co 
                        ON ct.ConferenceId = co.ConferenceId
            WHERE
                ct.ConferenceTransferTypeId = 1 AND
                ct.DateStarted IS NOT NULL AND
                ct.CallerUserId = @agentId AND
                ct.DateInitiated BETWEEN @dateFrom AND @dateTo
            ) AS c
) CallTransfered

关键部分是CASE WHEN c.RowNumber = 1 THEN c.OfferId END,所以除了第一个实例之外,您传递的是NULL,因此最终结果将只包含每个OfferId一次。

【讨论】:

    【解决方案2】:

    你需要按OfferId分组,然后再分组

    OUTER APPLY
    (
        SELECT 
            STRING_AGG(CAST(c.OfferId AS NVARCHAR(MAX)), ';') AS OfferDetails, 
            STRING_AGG(c.CustomTransferDetails, ';') AS CustomTransferDetails
        FROM (
            SELECT
                co.OfferId,
                STRING_AGG(CAST(ct.ConferenceId AS NVARCHAR(MAX)), ';') AS CustomTransferDetails
            FROM ConferenceTransfer ct
            INNER JOIN ConferenceOffer co ON ct.ConferenceId = co.ConferenceId
            WHERE
                ct.ConferenceTransferTypeId = 1 AND
                ct.DateStarted IS NOT NULL AND
                ct.CallerUserId = @agentId AND
                ct.DateInitiated BETWEEN @dateFrom AND @dateTo
            GROUP BY
                co.OfferId
        ) c
    ) CallTransfered
    

    这显然只适用于一个DISTINCT。如果您需要两者都不同,您可以重新拆分值,区分它们并重新聚合

    OUTER APPLY
    (
        SELECT 
            (
                SELECT
                    STRING_AGG(s.value, ';')
                FROM (
                    SELECT DISTINCT s.value
                    FROM STRING_SPLIT(OfferDetails, ';') s
                ) s
            ) AS OfferDetails, 
            (
                SELECT
                    STRING_AGG(s.value, ';')
                FROM (
                    SELECT DISTINCT s.value
                    FROM STRING_SPLIT(ConferenceId, ';') s
                ) s
            ) AS CustomTransferDetails
        FROM (
            SELECT
                STRING_AGG(CAST(co.OfferId AS NVARCHAR(MAX)), ';') AS OfferDetails, 
                STRING_AGG(CAST(ct.ConferenceId AS NVARCHAR(MAX)), ';') AS CustomTransferDetails
            FROM ConferenceTransfer ct
            INNER JOIN ConferenceOffer co ON ct.ConferenceId = co.ConferenceId
            WHERE
                ct.ConferenceTransferTypeId = 1 AND
                ct.DateStarted IS NOT NULL AND
                ct.CallerUserId = @agentId AND
                ct.DateInitiated BETWEEN @dateFrom AND @dateTo
            GROUP BY
                co.OfferId
        ) c
    ) CallTransfered
    

    【讨论】:

      猜你喜欢
      • 2019-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-18
      • 2020-05-19
      • 2021-01-03
      相关资源
      最近更新 更多