2

我需要在进行 GROUP BY 时找出值来自的行 ID。

首先创建并填充一个“播放对象”

-- vertical coalesce with row-source of value :) instead of column-source of value as in horizontal coalesce :)
CREATE TABLE #TBL(ID INT, GR INT, A INT, B INT)
INSERT INTO #TBL
SELECT 1,1,1,NULL
UNION ALL SELECT 2,1,NULL,2
UNION ALL SELECT 3,1,NULL,3
UNION ALL SELECT 4,2,2,NULL
UNION ALL SELECT 5,2,NULL,NULL
UNION ALL SELECT 6,2,6,NULL

选择最小值很简单:

SELECT GR, MIN(A) A, MIN(B) B,
    'Which first available row did A come from?' A_ID, 
    'Which first available row did B come from?' B_ID 
FROM #TBL
GROUP BY GR

但回答问题不是!

我试图做子查询,但由于值来自不同的行,它不起作用:

SELECT a.*
from #TBL a
    join (
    SELECT GR, MIN(A) A, MIN(B) B,
        'Which row did A come from?' A_ID, 
        'Which row did B come from?' B_ID
    FROM #TBL
    GROUP BY GR) b on a.GR = b.GR and a.A = b.A and a.B = b.B
--DROP TABLE #TBL

请帮忙。

4

3 回答 3

2

我不确定它是否会执行连接/外部应用(我认为它会),但这会起作用:

WITH CTE AS
(   SELECT  GR, 
            A, 
            B, 
            ID, 
            MinA = MIN(A) OVER(PARTITION BY GR), 
            MinB = MIN(B) OVER(PARTITION BY GR)
    FROM    #TBL
)
SELECT  GR,
        A = MIN(A),
        B = MIN(B),
        A_ID = MIN(CASE WHEN MinA = A THEN ID END),
        B_ID = MIN(CASE WHEN MinB = B THEN ID END)
FROM    CTE
GROUP BY GR;

在这个小样本上,统计数据表明这个表现更好:

使用聚合

(估计)查询成本 13%

表“工作台”。扫描计数 3,逻辑读取 21,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

使用外部应用

(估计)查询成本 87%

表“工作台”。扫描计数 16,逻辑读取 42,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

但是您可能会发现带有索引的实际示例会有所不同。

于 2013-09-26T16:23:56.870 回答
1

这应该这样做:

SELECT  DISTINCT 
        T1.GR,
        T2.A,
        T3.B,
        T2.ID A_ID,
        T3.ID B_ID
FROM #TBL T1
OUTER APPLY (SELECT TOP 1 *
             FROM #TBL
             WHERE GR = T1.GR
             AND A IS NOT NULL
             ORDER BY A, ID) T2
OUTER APPLY (SELECT TOP 1 *
             FROM #TBL
             WHERE GR = T1.GR
             AND B IS NOT NULL
             ORDER BY B, ID) T3

结果:

╔════╦═══╦══════╦══════╦══════╗
║ GR ║ A ║  B   ║ A_ID ║ B_ID ║
╠════╬═══╬══════╬══════╬══════╣
║  1 ║ 1 ║ 2    ║    1 ║ 2    ║
║  2 ║ 2 ║ NULL ║    4 ║ NULL ║
╚════╩═══╩══════╩══════╩══════╝
于 2013-09-26T16:19:30.540 回答
0
;WITH CTEA AS
(   SELECT  ID, GR, A, ROW_NUMBER() OVER(PARTITION BY GR ORDER BY A) AS 'RowNum'
    FROM    #TBL where A is not null
),    CTEB AS
(   SELECT  ID, GR, B, ROW_NUMBER() OVER(PARTITION BY GR ORDER BY B) AS 'RowNum'
    FROM    #TBL where B  is not null
)
select  CTEA.GR, CTEA.A, CTEA.ID, CTEB.B, CTEB.ID
  from  CTEA 
  jull  outer join  CTEB
    on  CTEA.GR = CTEB.GR
   and  CTEA.RowNum = 1 
   and  CTEB.RowNum = 1
于 2013-09-26T17:13:52.547 回答