SQL行中有1行多行

时间:2017-06-07 19:32:10

标签: sql sql-server select

问题是如果要输入太多记录

           |    id   |    name   |    age    |   Tel
------------------------------------------
      1    |    1   |   Frank   |    40     |   null
      2    |    1   |   null    |    50     |   7834xx
      3    |    1   |   Alex    |    null   |   null
      4    |    1   |   null    |    20     |   null
      5    |    2   |   James   |    null   |   4121xx

我的查询:

 select id, max(name) as name, max(age) as age, max(tel) as tel
 from Table group by id;

结果=返回最大值像:

           |    id   |   name    |    age    |   Tel
------------------------------------------
      1    |    1    |   Frank   |    50     |  7834xx

但我需要像这样的Select Query: 例如:(也许):    select id,lastRowsNotNull(name)as name,lastRowsNotNull(age)as age,lastRowsNotNull(tel)as table from table group by id;

           |    id   |   name    |    age    |   Tel
------------------------------------------
      1    |    1    |   Alex    |    20     |  7834xx

我该怎么办?恳求?

2 个答案:

答案 0 :(得分:2)

drop table if exists dbo.TableC;

create table dbo.TableC (
Ident int primary key
, Id int
, name varchar(100)
, age int
, Tel varchar(100)
);

insert into dbo.TableC (Ident, Id, name, age, Tel)
values (1, 1, 'Frank', 40, null)
, (2, 1, null, 50, '7834xx')
, (3, 1, 'Alex', null, null)
, (4, 1, null, 20, null)
, (5, 2, 'James', null, '4121xx');

select
*
from (
select
    MIN(t.Ident) as Ident
    , t.id
from dbo.TableC t
group by t.Id
) t
outer apply (
    select
        top (1)
        tn.name
    from dbo.TableC tn
    where tn.name is not null
        and tn.Id = t.Id
    order by tn.Ident desc
) tname
outer apply (
    select
        top (1)
        ta.age
    from dbo.TableC ta
    where ta.age is not null
        and ta.Id = t.Id
    order by ta.Ident desc
) tage
outer apply (
    select
        top (1)
        tt.tel
    from dbo.TableC tt
    where tt.Tel is not null
        and tt.Id = t.Id
    order by tt.Ident desc
) ttel

答案 1 :(得分:1)

我尝试通过引入Cross Apply并选择顶部列值来简化逻辑 Demo

主要逻辑

SELECT id, name, age, Tel FROM 
(SELECT MIN(rn) AS rn, id
 FROM 
 #RecordsTable
 GROUP BY id
) A
CROSS APPLY(    
SELECT 
     (SELECT TOP 1 name FROM #RecordsTable WHERE name IS NOT NULL AND id = A.id Order by rn DESC) name,
     (SELECT TOP 1 age FROM #RecordsTable WHERE age IS NOT NULL AND id = A.id Order by rn DESC) age,
     (SELECT TOP 1 Tel FROM #RecordsTable WHERE Tel IS NOT NULL AND id = A.id Order by rn DESC) Tel    
) B;

完整查询

IF OBJECT_ID('tempdb..#RecordsTable') IS NULL
BEGIN
  CREATE TABLE tempdb..#RecordsTable(rn INT IDENTITY(1, 1) NOT NULL, id INT, name VARCHAR(MAX), age INT, Tel VARCHAR(MAX));
END

;WITH RecordsTable AS(
  SELECT 1 AS id, 'Frank' AS name, 40 AS age, NULL AS Tel UNION ALL
  SELECT 1 , NULL, 50, '7834xx' UNION ALL
  SELECT 1, 'Alex', null, null UNION ALL
  SELECT 1, null, 20, null UNION ALl
  SELECT 2, 'James', null, '4121xxx'
)
INSERT INTO #RecordsTable
SELECT id, name, age, Tel FROM RecordsTable;

SELECT id, name, age, Tel FROM 
(SELECT MIN(rn) AS rn, id
 FROM 
 #RecordsTable
 GROUP BY id
) A
CROSS APPLY( 

SELECT 
     (SELECT TOP 1 name FROM #RecordsTable WHERE name IS NOT NULL AND id = A.id Order by rn DESC) name,
     (SELECT TOP 1 age FROM #RecordsTable WHERE age IS NOT NULL AND id = A.id Order by rn DESC) age,
     (SELECT TOP 1 Tel FROM #RecordsTable WHERE Tel IS NOT NULL AND id = A.id Order by rn DESC) Tel

) B;

DROP TABLE #RecordsTable

输出

1   Alex    20  7834xx
2   James   NULL    4121xxx