如果值为空,则合并行

时间:2015-07-21 08:10:31

标签: sql sql-server tsql merge group-by

我正在使用 SQL-Server 2008 。我需要将行与相同的Name组合在一起,并在以下情况下增加计数器:

  1. 同一Id's的{​​{1}} Nameblank
  2. 如果IdNULL,则不合并行
  3. 如果具有相同的Name但不同的Ids
  4. ,则不合并行

    现在输出:

    Name    Id   Cnt
    John    1     1
    Peter   2     2 -- This Peter with the same Id have 2 entries so Cnt = 2
    Peter   3     1 -- This is other Peter with 1 entry so Cnt = 1
    Lisa    4     1
    Lisa   NULL   1
    David   5     1
    David         1 -- here Id is blank ''
    Ralph         2 -- Ralph have both rows with blank Id so Cnt = 2
    

    期望的输出:

    Name    Id   Cnt
    John    1     1
    Peter   2     2
    Peter   3     1
    Lisa    4     1
    Lisa   NULL   1 -- null still here
    David   5     2 -- merged with blank '' so Cnt = 2
    Ralph         2 -- merged both blanks '' so Cnt = 2
    

    SQL-Query:

    这是我现在正在使用的示例查询:

    SELECT Name, 
           Id, 
           COUNT(Id) AS Cnt
    FROM Employees                       
    WHERE Condition = 1                 
    GROUP BY Name, Id
    

    我尝试了什么:

    MAX子句中向Id添加了汇总SELECT,仅按Name分组,但在这种情况下,合并的行具有NULL值并且具有相同的值不同Id's的名字对我来说有什么不对。

    SELECT Name, 
           MAX(Id), -- added aggregate
           COUNT(Id) AS Cnt
    FROM Employees                       
    WHERE Condition = 1                 
    GROUP BY Name -- grouped by Name only
    

    你有什么想法吗?如果对问题一无所知 - 请问我,我会提供更多细节。

    更新

    DDL

    CREATE TABLE Employees
    (
      Name NVARCHAR(40),
      Id NVARCHAR(40)
    );
    

    DML

    INSERT INTO Employees VALUES
     ('John' ,   '1')
    ,('Peter',   '2')
    ,('Peter',   '2')
    ,('Peter',   '3')
    ,('Lisa' ,   '4')
    ,('Lisa' ,  NULL)
    ,('David',   '5')
    ,('David',   '')
    ,('Ralph',   '')
    ,('Ralph',   '')
    

    DEMO: this link

6 个答案:

答案 0 :(得分:1)

您可以在$(document).on('mouseup', '.m1', function(){ alert('div mouseup '); }); $(document).on('click', 'ul li', function(){ alert("ul li- clicked"); }); 内使用CASE声明。它允许您为员工空白时设置Id = [some value]。查询可以是这样的:

SELECT

答案 1 :(得分:1)

修改

DECLARE @Data table (Name varchar(10), Id varchar(10)) -- Id must be varchar for blank value
INSERT @Data VALUES
('John', '1'),
('Peter', '2'),('Peter', '2'), 
('Peter', '3'),--('Peter', ''), --For test
('Lisa', '4'),
('Lisa', NULL),
('David', '5'),
('David', ''),
('Ralph', ''), ('Ralph', '')
SELECT 
    Name, 
    Id, 
    COUNT(*) + ISNULL(
        (SELECT COUNT(*) FROM @data WHERE Name = d.Name AND Id = '' AND d.Id <> '')
    , 0) AS Cnt 
FROM @data d 
WHERE 
    Id IS NULL 
    OR Id <> '' 
    OR NOT EXISTS(SELECT * FROM @data WHERE Name = d.Name AND Id <> '')
GROUP BY Name, Id

答案 2 :(得分:1)

具有窗口功能的版本:

SELECT Name,ID, Cnt from
( select *, sum(1-AmtBlank) over (partition by Name, ID) + sum(case id when 0 then 1 else 0 end) over (partition by Name) Cnt,
       rank()  over (partition by Name order by AmtBlank  ) rnk,
       row_number() over (partition by Name, ID order by AmtBlank) rnr
    FROM (select * , case id when '' then 1 else 0 end AmtBlank from Employees /*WHERE Condition = 1*/ ) e
) c where  rnr=1 and rnk = 1

这使用case id when '' then 1 else 0 end AmtBlank来保留每行空白金额(使非空白1-AmtBlank的金额)和2个窗口函数的金额,一个id为每个名称和id的计数({{1 }和)名称部分中所有空格的计数(sum(1-AmtBlank) over (partition by Name, ID)sum(case id when 0 then 1 else 0 end) over (partition by Name)用于随后仅获取组的第一行,而row_number仅用于在没有id的记录时包含空白记录。

答案 3 :(得分:0)

试试这个。使用cte和join

;with cte as (
SELECT Name, 
       Id, 
       COUNT(*) AS Cnt
FROM Employees                       
WHERE isnull(Id,1)<>''               
GROUP BY Name, Id
),

cte2 as (SELECT Name,id, COUNT(*) AS Cnt    FROM Employees WHERE Id='' GROUP BY Name,id)

select cte.Name,cte.Id,(cte.cnt + ISNULL(cte2.Cnt,0)) as cnt
from cte 
left JOIN  cte2
on cte.Name = cte2.Name 
union all 
select cte2.Name,cte2.Id,cte2.cnt
from cte2 
left JOIN  cte
on cte.Name = cte2.Name 
where cte.Name is null

答案 4 :(得分:0)

这个简单的语法与旧版本或其他RDBMS兼容 - 自我解释评论
编辑:

select name, id, count(*) from (
    -- adds "normal" records
    select name, id from Employees where id is null or id <> ''
    -- adds one record to each name-notBlankId for each blank id  (David, Peter if you add 'Peter','')
    -- uncomment /*or id is null*/ if you want even null ids to recieve merged blanks
    union all
    select e1.name, e1.id
    from (select distinct name, id from Employees where id <> '' /*or id is null*/ ) as e1 
    inner join (select name, id from Employees where id = '') as e2 on e1.name = e2.name
    -- adds records that can't be merged (Ralph)
    union all
    select name, id from Employees e1
    where e1.id = ''
      and not exists(select * from Employees e2 where e1.name = e2.name and e2.id <> '')
) as fullrecords
group by name, id

答案 5 :(得分:0)

你可以尝试这样的事情。

;WITH NonBlanks AS
(
  SELECT Name, 
         Id, 
         COUNT(ISNULL(Id, 1)) AS Cnt
  FROM Employees
  WHERE ISNULL(Id,0) <> ''
  GROUP BY Name, Id
 )
,Blanks AS
(
  SELECT Name, 
         Id, 
         COUNT(ISNULL(Id, 1)) AS Cnt
  FROM Employees
  WHERE ID = ''
  GROUP BY Name, Id
)
SELECT CASE WHEN nb.NAME IS NULL THEN b.NAME ELSE nb.NAME END NAME,
       CASE WHEN nb.NAME IS NULL THEN b.Id ELSE nb.Id END Id,
       (ISNULL(nb.Cnt,0) + ISNULL(b.Cnt,0)) Cnt
FROM NonBlanks nb FULL JOIN  Blanks b 
     ON nb.Name = b.Name