Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server TSQL分组并从子查询中选择行数_Sql Server_Tsql_Sql Server 2012_Sql Server 2017 - Fatal编程技术网

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

Sql server TSQL分组并从子查询中选择行数,sql-server,tsql,sql-server-2012,sql-server-2017,Sql Server,Tsql,Sql Server 2012,Sql Server 2017,我有下表 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 St

我有下表

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
对于给定的AccountID,我想选择AddressLine和City。
如果帐户具有相同的
AddressLine
,则应选择该AddressLine值,否则返回“多个”。
如果帐户具有相同的
城市
,则应选择该城市值,否则返回“多个”

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

AccountID  AddressLine City
1          Multiple    New York
这是

下面是我的问题(不起作用)。我认为问题在于分组和从子队列中选择计数

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

我想这应该可以。我使用该函数按汇总组中的地址,因为您只想在有单个值的情况下显示该值。我省略了where谓词,只显示了一个帐户,但将其添加回去很简单

;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

下面是另一个使用交叉应用的解决方案

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

下面是一个可以在SSMS中运行的简单示例:

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;
AccountID1返回

+-----------+-------------+----------+
| AccountID | AddressLine |   City   |
+-----------+-------------+----------+
|         1 | Multiple    | New York |
+-----------+-------------+----------+
AccountID2返回

+-----------+----------------+---------------+
| AccountID |  AddressLine   |     City      |
+-----------+----------------+---------------+
|         2 | Lombard Street | San Francisco |
+-----------+----------------+---------------+

当然,这并没有考虑到多个城市价值观的可能性。

不妨将我的价值观加入其中。它并不比其他任何东西都好,但不管怎样,它就在这里

SELECT
    A.AccountID,
    T1.AddressLine,
    T2.City
FROM Accounts A
INNER JOIN
(
    SELECT 
        ad.AccountID,
        CASE WHEN COUNT(DISTINCT(ad.AddressLine)) > 1 THEN 'Multiple' ELSE MIN(ad.AddressLine) END AS AddressLine
    FROM Addresses ad   
    GROUP BY ad.AccountID, ad.city
) T1 ON T1.AccountID = A.AccountID
INNER JOIN
(
    SELECT 
        ad.AccountID,
        CASE WHEN COUNT(DISTINCT(ad.City)) > 1 THEN 'Multiple' ELSE MIN(ad.City) END AS City
    FROM Addresses ad   
    GROUP BY ad.AccountID
) T2
ON T2.AccountID = A.AccountID
WHERE 
    a.AccountID = 1