哪行行最小值来自(垂直合并)

时间:2013-09-26 16:08:22

标签: sql sql-server-2008 tsql

我需要在执行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

请帮忙。

3 个答案:

答案 0 :(得分: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。

但是你可能会发现索引的真实例子会有所不同。

答案 1 :(得分: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 ║
╚════╩═══╩══════╩══════╩══════╝

答案 2 :(得分: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