从某些列满足聚合条件的行中查找值?

时间:2017-01-26 16:15:05

标签: sql sql-server tsql

SQL SERVER 2008 R2。两个表具有1-many关系,并且希望两者都有一些字段,但在很多方面,只需要来自某一行的值。该行由某些条件指定,在我的情况下,该行应该具有该PaymentId的最小ClaimId。

IF OBJECT_ID('tempdb..#Payments') IS NOT NULL DROP TABLE #Payments
CREATE TABLE #Payments ( PaymentId int UNIQUE NOT NULL )
INSERT INTO #Payments ( PaymentId )
VALUES (1), (2), (3)

IF OBJECT_ID('tempdb..#Claims') IS NOT NULL DROP TABLE #Claims
CREATE TABLE #Claims ( PaymentId int NOT NULL, ClaimId int NOT NULL, FirstName varchar(50) NOT NULL )
INSERT INTO #Claims ( PaymentId, ClaimId, FirstName )
VALUES (1, 51,'Joe'), (1, 57,'Jane'), (2, 62,'Spot'), (2, 63,'Rover'), (3, 88,'Sue'), (3, 89,'Sally')

SELECT * FROM #Payments p
JOIN #Claims c ON p.PaymentId=c.PaymentId
WHERE c.ClaimId=MIN(ClaimId)
GROUP BY p.PaymentId
HAVING MIN(ClaimId)

期望的结果如下,其中声明来自具有给定paymentId的最小claimId的行。 ClaimId可能不会被订购,因此寻求最低限度,而不是首先。

PaymentId   ClaimId   FirstName
1           51        Joe
2           62        Spot
3           88        Sue

我很乐意提及现有的问题/答案,但我不知道怎么说这个,我发现类似的东西。也许是Get field value from a record that causes an aggregate condition to be true,但我对此并不了解。

5 个答案:

答案 0 :(得分:2)

您可以使用ROW_NUMBER窗口功能,如下所示:

SELECT PaymentId, ClaimId, FirstName
FROM
(
    SELECT 
        p.PaymentId, 
        c.ClaimId, 
        c.FirstName, 
        ROW_NUMBER() OVER (PARTITION BY p.PaymentId ORDER BY c.ClaimId) as RN 
    FROM #Payments p
    JOIN #Claims c ON p.PaymentId=c.PaymentId
) as T
WHERE RN = 1

答案 1 :(得分:1)

在SQL Server中,我喜欢使用outer apply

select p.*, c.*
from #Payments p outer apply
     (select top 1 c.*
      from #Claims c
      where c.paymentid = p.paymentid
      order by c.claimid
     ) c;

答案 2 :(得分:1)

使用foreach(DataRow row in ((DataTable)this.grdPart.DataSource).Select("Seleccionar= true")) { string sub = row["SUB"].ToString(); string p1 = row["P1"].ToString(); string p2 = row["P2"].ToString(); string p3 = row["P3"].ToString(); }

的解决方案
RANK()

答案 3 :(得分:1)

使用windows function row_number提供订单

;with cte as
(
select PaymentID, ClaimID, row_number() over (partition by PaymentID order by ClaimID ) as rn
from #Claims
)

select p.*,cte.ClaimID
from #Payments p
join cte on cte.paymentID = p.paymentID
where rn=1 --limits to earliest claimid

答案 4 :(得分:1)

两个句子都返回相同的结果,首先为每个PaymentId选择MIN(ClaimId):

SELECT P.*, C.*
FROM #Payments P
    INNER JOIN #Claims C ON C.PaymentId = P.PaymentId
WHERE C.ClaimID IN (SELECT MIN(ClaimID) OVER (PARTITION BY PaymentId) FROM #Claims);

第二次使用CTE在加入Payments表之前找到MIN(ClaimId):cº

WITH PY AS
(
    SELECT PaymentId, MIN(ClaimId) as ClaimID
    FROM #Claims
    GROUP BY PaymentId
)
SELECT PY.PayMentId, PY.ClaimId, C.FirstName, P.*
FROM PY
     LEFT JOIN #Claims c ON p.ClaimId = c.ClaimId;
     LEFT JOIN #Payments P ON P.PaymentId = PY.PaymentId


+-----------+---------+-----------+
| PayMentId | ClaimId | FirstName |
+-----------+---------+-----------+
| 1         | 51      | Joe       |
+-----------+---------+-----------+
| 2         | 62      | Spot      |
+-----------+---------+-----------+
| 3         | 88      | Sue       |
+-----------+---------+-----------+

在此处查看:http://rextester.com/KRT45653