TSQL分组并从子查询中选择行数

问题描述 投票:1回答:4

我有下表

AccountID   Name
1           Foo Bar
2           Jon Dow

AccountID   AddressLine         City
1           123 Test RD         New York
1           456 Test RD         New York
2           Lombard Street      San Francisco
2           Lombard Street      San Francisco

对于给定的帐户ID,我想选择地址行和城市。如果帐户具有相同的AddressLine,则应选择该AddressLine值,否则返回'Multiple'。如果帐户具有相同的City,则应选择该城市值,否则返回“多个”。

例如,对于帐户ID 1,查询应返回

AccountID  AddressLine City
1          Multiple    New York

这里是SQLFiddle

以下是我的查询(不起作用)。我认为问题是分组并从子查询中选择计数

SELECT
    A.AccountID,
    CASE
        WHEN T1.CNT = 1
            THEN T1.AddressLine
        ELSE 'Multiple'
    END AS 'Address Line',
    CASE WHEN T2.CNT = 1
        THEN T2.City
    ELSE 'Multiple'
    END AS 'City'   
FROM Accounts A
INNER JOIN
(
    SELECT 
        ad.AccountID,
        COUNT(DISTINCT(ad.AccountID)) AS CNT,
        ad.AddressLine
    FROM Addresses ad   
    GROUP BY ad.AccountID, ad.AddressLine
) T1 ON T1.AccountID = A.AccountID
INNER JOIN
(
    SELECT 
        ad.AccountID,
        COUNT(DISTINCT(ad.AccountID)) AS CNT,
        ad.City
    FROM Addresses ad   
    GROUP BY ad.AccountID, ad.City
) T2
ON T2.AccountID = A.AccountID
WHERE 
    a.AccountID = 1
sql-server tsql sql-server-2012 sql-server-2017
4个回答
0
投票

我认为应该这样做。我使用了string_agg函数来汇总组中的地址,因为无论如何您只想显示一个值。我放弃了仅显示单个帐户的where谓词,但是将其添加回去很简单。

string_agg

0
投票

这里是另一种使用;with dist as ( SELECT DISTINCT AccountID ,AddressLine ,City FROM addresses ) ,agg as ( SELECT AccountID ,COUNT(*) as AddressCount ,STRING_AGG(AddressLine, ',') as Address ,STRING_AGG(City, ',') as City FROM dist GROUP BY AccountID ) select AccountID ,CASE AddressCount WHEN 0 THEN 'N/A' WHEN 1 THEN Address ELSE 'Multiple' END as Address ,CASE AddressCount WHEN 0 THEN 'N/A' WHEN 1 THEN City ELSE 'Multiple' END as City from agg 的解决方案

CROSS APPLY

0
投票

这是您可以在SSMS中运行的简单示例:

SELECT
    AccountID
,   CASE 
        WHEN x.countOfDictinctAddressLine = 1
        THEN x.firstAddressLine
        ELSE 'Multiple'
        END AS AddressLine
,   City
FROM
    Addresses AS source
CROSS APPLY
    (
        SELECT
            COUNT(DISTINCT AddressLine) AS countOfDictinctAddressLine
        ,   MIN(AddressLine) AS firstAddressLine
        FROM
            Addresses
        WHERE
            AccountID = source.AccountID
    ) x
GROUP BY
    AccountID
,   x.countOfDictinctAddressLine
,   x.firstAddressLine
,   City;

AccountID 1退货

DECLARE @Accounts TABLE ( AccountID INT, Name VARCHAR(50) );
INSERT INTO @Accounts ( AccountID, Name ) 
    VALUES ( 1, 'Foo Bar' ), ( 2, 'Jon Dow' );

DECLARE @Addresses TABLE ( AccountID INT, AddressLine VARCHAR(50), City VARCHAR(50) );
INSERT INTO @Addresses ( AccountID, AddressLine, City )
    VALUES ( 1, '123 Test Rd', 'New York' ), ( 1, '456 Test Rd', 'New York' ), ( 2, 'Lombard Street', 'San Francisco' ), ( 2, 'Lombard Street', 'San Francisco' );

SELECT
    Accounts.AccountID,
    AddressRecords.AddressLine,
    Addresses.City
FROM @Accounts AS Accounts
INNER JOIN @Addresses AS Addresses
    ON Accounts.AccountID = Addresses.AccountID
OUTER APPLY (

    SELECT CASE
        WHEN ( SELECT COUNT ( DISTINCT ( x.AddressLine ) ) FROM @Addresses AS x WHERE x.AccountID = Accounts.AccountID ) > 1 THEN 'Multiple'
        ELSE ( SELECT DISTINCT AddressLine FROM @Addresses AS x WHERE x.AccountID = Accounts.AccountID )
    END AS AddressLine

) AS AddressRecords
WHERE
    Accounts.AccountID = 1
GROUP BY
    Accounts.AccountID, AddressRecords.AddressLine, Addresses.City;

AccountID 2退货

+-----------+-------------+----------+
| AccountID | AddressLine |   City   |
+-----------+-------------+----------+
|         1 | Multiple    | New York |
+-----------+-------------+----------+

0
投票

也可以将我的加入混合。它并不比其他任何一个都要好,但是无论如何它还是在这里...

+-----------+----------------+---------------+
| AccountID |  AddressLine   |     City      |
+-----------+----------------+---------------+
|         2 | Lombard Street | San Francisco |
+-----------+----------------+---------------+
© www.soinside.com 2019 - 2024. All rights reserved.