如何从 SQL 查询的每个唯一结果中提取第一个结果?
How do I pull the first result from each unique result of an SQL query?
我正在尝试从每个唯一的 TnID 记录中提取第一个结果,以便我可以将其提取到另一个数据库中。
SELECT DISTINCT [Tenant Name]
,CARL_Tenant_Contacts.ID
,Carl_current_tenants.TnID
,PrId FROM CARL_Tenant_Contacts
JOIN CARL_Current_Tenants ON CARL_Current_Tenants.ID = CARL_Tenant_Contacts.TnID
WHERE [Tenant Name] IS NOT NULL
and [Tenant Name] != ''
这是我目前得到的代码,但它并不完全符合我的要求。
目前结果是:
(还有很多,这只是一个小例子。)
但我想要的东西会 return 每个 TnID 的名字,例如,来自 TnID1 我想要 Ms Julie Robinson,来自 TnID2 我想要 Ms Julia Gregg,TnID3 Mr Andrew Leigh webb 等等.
这是可行的还是我在尝试不可能的事情?
应该这样做:
;WITH CTE
AS (SELECT DISTINCT
[Tenant Name]
, CARL_Tenant_Contacts.ID
, Carl_current_tenants.TnID
, PrId
, RN = ROW_NUMBER() OVER(PARTITION BY Carl_current_tenants.TnID ORDER BY CARL_Tenant_Contacts.ID)
FROM CARL_Tenant_Contacts
JOIN CARL_Current_Tenants ON CARL_Current_Tenants.ID = CARL_Tenant_Contacts.TnID
WHERE [Tenant Name] IS NOT NULL
AND [Tenant Name] != '')
SELECT A.[Tenant Name]
, A.ID
, A.TnID
, A.PrId
FROM CTE AS A
WHERE RN = 1;
修改以处理 DISTINCT:
;WITH A
AS (SELECT DISTINCT
[Tenant Name]
, CARL_Tenant_Contacts.ID
, Carl_current_tenants.TnID
, PrId
FROM CARL_Tenant_Contacts
JOIN CARL_Current_Tenants ON CARL_Current_Tenants.ID = CARL_Tenant_Contacts.TnID
WHERE [Tenant Name] IS NOT NULL
AND [Tenant Name] != ''),
CTE
AS (SELECT A.[Tenant Name]
, A.ID
, A.TnID
, A.PrId
, RN = ROW_NUMBER() OVER(PARTITION BY A.TnID ORDER BY A.ID)
FROM A)
SELECT A.[Tenant Name]
, A.ID
, A.TnID
, A.PrId
FROM CTE AS A
WHERE RN = 1;
不同的阐述
由于另一个答案是以 "bad" 的方式实现了结果,我会选择另一个派生的 table。如果您在与 DISTINCT
子句相同的级别应用 ROW_NUMBER()
函数,它实际上不会执行 DISTINCT。
我认为这值得指出,因为如果您删除带有行数限制的 WHERE
子句,您最终会在输出中出现重复记录。
示例:
select distinct
tnid,
id,
row_number() over (partition by tnid order by id) as rn
from (
select 1 as tnid, 1 as id
union all select 1,7
union all select 2,3
union all select 2,3 -- duplicate record
union all select 2,9
union all select 1,5
) foo
结果:
tnid | id | rn
-----+----+----
1 | 1 | 1
1 | 5 | 2
1 | 7 | 3
2 | 3 | 1
2 | 3 | 2 -- duplicate record showing in distinct, because it takes the rn column as well
2 | 9 | 3
原回答
您需要一个 ROW_NUMBER()
window 函数来枚举每个 TnID
从最低 ID
开始的行。然后只需使用带有 row_num = 1
的 WHERE
子句将输出限制为仅那些行:
SELECT [Tenant Name], ID, TnID, PrId
FROM (
SELECT
*
, ROW_NUMBER() OVER (PARTITION BY TnID ORDER BY ID) AS row_num
FROM (
SELECT DISTINCT
[Tenant Name]
, ctc.ID
, cct.TnID
, PrId
FROM
CARL_Tenant_Contacts ctc
JOIN CARL_Current_Tenants cct ON cct.ID = ctc.TnID
WHERE
[Tenant Name] IS NOT NULL
AND [Tenant Name] != ''
) foo
) bar
WHERE row_num = 1
我花时间为您的 table 分配别名以缩短查询。
我正在尝试从每个唯一的 TnID 记录中提取第一个结果,以便我可以将其提取到另一个数据库中。
SELECT DISTINCT [Tenant Name]
,CARL_Tenant_Contacts.ID
,Carl_current_tenants.TnID
,PrId FROM CARL_Tenant_Contacts
JOIN CARL_Current_Tenants ON CARL_Current_Tenants.ID = CARL_Tenant_Contacts.TnID
WHERE [Tenant Name] IS NOT NULL
and [Tenant Name] != ''
这是我目前得到的代码,但它并不完全符合我的要求。
目前结果是:
(还有很多,这只是一个小例子。)
但我想要的东西会 return 每个 TnID 的名字,例如,来自 TnID1 我想要 Ms Julie Robinson,来自 TnID2 我想要 Ms Julia Gregg,TnID3 Mr Andrew Leigh webb 等等.
这是可行的还是我在尝试不可能的事情?
应该这样做:
;WITH CTE
AS (SELECT DISTINCT
[Tenant Name]
, CARL_Tenant_Contacts.ID
, Carl_current_tenants.TnID
, PrId
, RN = ROW_NUMBER() OVER(PARTITION BY Carl_current_tenants.TnID ORDER BY CARL_Tenant_Contacts.ID)
FROM CARL_Tenant_Contacts
JOIN CARL_Current_Tenants ON CARL_Current_Tenants.ID = CARL_Tenant_Contacts.TnID
WHERE [Tenant Name] IS NOT NULL
AND [Tenant Name] != '')
SELECT A.[Tenant Name]
, A.ID
, A.TnID
, A.PrId
FROM CTE AS A
WHERE RN = 1;
修改以处理 DISTINCT:
;WITH A
AS (SELECT DISTINCT
[Tenant Name]
, CARL_Tenant_Contacts.ID
, Carl_current_tenants.TnID
, PrId
FROM CARL_Tenant_Contacts
JOIN CARL_Current_Tenants ON CARL_Current_Tenants.ID = CARL_Tenant_Contacts.TnID
WHERE [Tenant Name] IS NOT NULL
AND [Tenant Name] != ''),
CTE
AS (SELECT A.[Tenant Name]
, A.ID
, A.TnID
, A.PrId
, RN = ROW_NUMBER() OVER(PARTITION BY A.TnID ORDER BY A.ID)
FROM A)
SELECT A.[Tenant Name]
, A.ID
, A.TnID
, A.PrId
FROM CTE AS A
WHERE RN = 1;
不同的阐述
由于另一个答案是以 "bad" 的方式实现了结果,我会选择另一个派生的 table。如果您在与 DISTINCT
子句相同的级别应用 ROW_NUMBER()
函数,它实际上不会执行 DISTINCT。
我认为这值得指出,因为如果您删除带有行数限制的 WHERE
子句,您最终会在输出中出现重复记录。
示例:
select distinct
tnid,
id,
row_number() over (partition by tnid order by id) as rn
from (
select 1 as tnid, 1 as id
union all select 1,7
union all select 2,3
union all select 2,3 -- duplicate record
union all select 2,9
union all select 1,5
) foo
结果:
tnid | id | rn
-----+----+----
1 | 1 | 1
1 | 5 | 2
1 | 7 | 3
2 | 3 | 1
2 | 3 | 2 -- duplicate record showing in distinct, because it takes the rn column as well
2 | 9 | 3
原回答
您需要一个 ROW_NUMBER()
window 函数来枚举每个 TnID
从最低 ID
开始的行。然后只需使用带有 row_num = 1
的 WHERE
子句将输出限制为仅那些行:
SELECT [Tenant Name], ID, TnID, PrId
FROM (
SELECT
*
, ROW_NUMBER() OVER (PARTITION BY TnID ORDER BY ID) AS row_num
FROM (
SELECT DISTINCT
[Tenant Name]
, ctc.ID
, cct.TnID
, PrId
FROM
CARL_Tenant_Contacts ctc
JOIN CARL_Current_Tenants cct ON cct.ID = ctc.TnID
WHERE
[Tenant Name] IS NOT NULL
AND [Tenant Name] != ''
) foo
) bar
WHERE row_num = 1
我花时间为您的 table 分配别名以缩短查询。