从SQL返回计数时,如何在计数不存在的分组项中包含该值?

时间:2015-10-30 13:57:37

标签: c# sql linq

现在已经有一段时间处理这个SQL难题了。表格的一部分如下所示。

这是一个多对多的表关系,其中一个声明可以有很多音符。因此,一个例子如下:

------------------------------------------
|   ClaimID  |   NoteID  |       Note    |
------------------------------------------
|    2387    |     1     |    Test 1     |
|    2387    |     2     |    Test 2     |
|    2387    |     3     |    Test 3     |
|    2532    |     4     |  Something 1  |
|    2539    |     5     |     abcd      |
|    2539    |     6     |    jklm       |
------------------------------------------

你明白了。

所以,当我运行查询时,我想要的结果是它应该显示从1到10的音符计数。如果计数存在,那么它应该显示计数,否则为0.在现实世界中,它的样子如下所示。

    [{
         "numOfNotes":1,
         "count":5916
     },{
        "numOfNotes":2,
        "count":1846
     },{
        "numOfNotes":3,
        "count":639
     },{
       "numOfNotes":4,
       "count":226
     },{
       "numOfNotes":5,
       "count":94
     },{
      "numOfNotes":6,
      "count":50
     },{
      "numOfNotes":7,
      "count":10
     },{
      "numOfNotes":8,
      "count":2
     },{
      "numOfNotes":9,
      "count":2
     },{
      "numOfNotes":11,
      "count":2
   }]

这是我使用C#和linq检索的数据库的查询返回。这是代码。

if (type == "e" || type == "p")
{
  //sub query to retrieve notes

  var subquery = from f in db.DBFileInfo
                 join c in db.Claims on f.FileID equals c.FileID into cl
                 from gp1 in cl.DefaultIfEmpty()
                 join n in db.Notes on gp1.ClaimID equals n.ClaimID into nt
                 from gp2 in nt.DefaultIfEmpty()
                 where f.ReportDate.Month == month && f.ReportDate.Year == year
                 group gp2 by gp2.ClaimID into g
                 select new
                 {
                       Key = g.Key,
                       Count = g.Count()
                 };

  //query to grop by notes count. Notes count is consider contact per claim
  var count = (from c in db.Claims
              join s in subquery on c.ClaimID equals s.Key
              where c.RecordType == type && 
              (c.Username != "RxService") 
              && (c.HIC3 != "J3A" && c.HIC3 != "J3C" && c.HIC3 != "H7N")
              group s by s.Count into g
              orderby g.Key
              select new
              {
                  NumOfNotes = g.Key,
                  count = g.Count()
              }).Take(10);
}

如果您在结果中注意到,1 - 11中有numOfNotes,但缺少10。那是因为没有任何具有10个音符的claimID。所以,在这种情况下,我仍然希望SQL返回"numOfNotes": 10, "count": 0。如果您注意到,我只询问了10个结果(Take(10)),因为每个声明可能有超过10个这样的说明我们不感兴趣。

在某些情况下,给定时间段内每个claimID不超过5个音符。在一个实例中,SQL的结果最多只能达到6.但我仍然希望结果最多为10,无论它是否存在。可能吗?

万一你感兴趣:这是我的SQL语句

SELECT 
    count(C.ClaimID) as count, N.NotesPerClaim 
FROM
    ClaimsTable C
INNER JOIN
    (SELECT 
         claimid, count(note) as NotesPerClaim 
     FROM
         NotesTable
     GROUP BY 
         ClaimID) as N ON N.ClaimID = C.ClaimID
WHERE 
    RecordType = 'e' AND 
    (Username <> 'RxService') AND 
    (HIC3 <> 'J3A' AND HIC3 <> 'J3C' AND HIC3 <> 'H7N')
GROUP BY 
    N.NotesPerClaim
ORDER BY 
    N.NotesPerClaim;

3 个答案:

答案 0 :(得分:1)

你好像想要一张数字表。这是一种方法:

WITH nums as (
      SELECT 1 as n
      UNION ALL
      SELECT n + 1
      FROM nums
      WHERE n < 10
     ),
     t as (
      SELECT count(C.ClaimID) as NumClaims, N.NotesPerClaim
      FROM ClaimsTable C JOIN
           (SELECT claimid, count(note) as NotesPerClaim
            FROM NotesTable
            GROUP BY ClaimID
           ) N
           ON N.ClaimID = C.ClaimID
      WHERE c.RecordType = 'e' AND 
            c.Username <> 'RxService' AND 
            c.HIC3 NOT IN ('J3A', 'J3C', 'H7N')
      GROUP BY N.NotesPerClaim
     )
SELECT nums.n as NotesPerClaim, t.NumClaims
FROM nums LEFT JOIN
     t
     ON nums.n = t.NotesPerClaim
ORDER BY NotesPerClaim;

答案 1 :(得分:0)

使用LEFT JOIN代替INNER JOIN

最好还是使用HIC3 NOT IN ('J3A', 'J3C', 'H7N')

SELECT count(C.ClaimID) AS count
     , N.NotesPerClaim
FROM ClaimsTable C
LEFT JOIN (
    SELECT  claimid
          , count(note) AS NotesPerClaim
    FROM NotesTable
    GROUP BY ClaimID
    ) AS N ON N.ClaimID = C.ClaimID
WHERE RecordType = 'e'
    AND (Username <> 'RxService')
    AND HIC3 NOT IN ('J3A', 'J3C', 'H7N')

GROUP BY N.NotesPerClaim
ORDER BY N.NotesPerClaim;

答案 2 :(得分:0)

注释表上的LEFT JOIN,并检查ISNULL条件。如果是notes中的NULL,则返回0。

这是概念的SQL Fiddle demo

您的代码应为:

`SELECT count(C.ClaimID) as count, ISNULL(N.NotesPerClaim,0) as NotesPerClaim
 FROM ClaimsTable C
 LEFT OUTER JOIN
 (SELECT claimid, count(note) as NotesPerClaim from NotesTable
 GROUP BY ClaimID) as N
 ON N.ClaimID = C.ClaimID
 WHERE RecordType = 'e' AND 
 (Username <> 'RxService') AND (HIC3 NOT IN ('J3A','J3C','H7N'))
 GROUP BY ISNULL(N.NotesPerClaim,0)
 ORDER BY N.NotesPerClaim;`