SSRS 2008 R2 - 仅在更改组时评估运行总计

时间:2012-06-11 18:23:44

标签: sql-server reporting-services ssrs-2008

我有一份报告,我在其中捕获患者信息,其中一些信息存储在患者表中,其中一些信息存储在观察表中。以出生日期为例,如果我计算了提供DOB的所有记录,由于加入观察表,我得到的患者总数远远超过患者总数。如何为每个组仅评估一次运行总计?

编辑:http://sqlfiddle.com/#!3/27b91/1/0处的一些示例数据。如果我从该查询中计算出生日期,我想要2作为答案;同样适合种族和民族。

3 个答案:

答案 0 :(得分:2)

以下对于您的具体情况可能是也可能不是正确的方法,但它可以是您可以使用的有用技术。

您可以在select语句中添加一些代码,以帮助自己回答诸如“下游”之类的问题(通过添加的标准或通过SSRS)。见this modification of your SQL Fiddle

select pid, firstName, lastName, dateOfBirth, obsName, obsValue, obsDate, 
      rowRank, CASE rowRank WHEN 1 THEN 1 ELSE 0 END AS countableRow
from 
(
select Person.pid, Person.firstName, Person.lastName, Person.dateOfBirth
      , Obs.obsName, Obs.obsValue, Obs.obsDate,
      ROW_NUMBER() OVER (PARTITION BY Person.pid, Person.firstName, Person.lastName, Person.dateOfBirth ORDER BY Obs.obsDate) AS rowRank
  from Person
    join Obs on Person.pId = Obs.pId
) rankedData

rowRank字段将创建一个与组相关的排名编号,这对您下游可能有用,也可能没用。 countableRow字段将为1或0,这样每个组将只有一行,其中只有一行。执行SUM(countableRow)将为您提供数据中适当数量的组。

现在,您可以通过在每个组的第一行中转出实际字段值而不是像1这样的常量标量来扩展此功能(如果您愿意)。因此,如果您有CASE rowRank WHEN 1 THEN dateOfBirth ELSE NULL END AS countableDOB,那么您可以使用此数据集获取每个不同生日的总人数。

当然,你可以使用像@ Russell的SQL这样的方法来做所有这些事情,所以这与可能与你的情况不符的特定下游要求最相关。

修改

显然,countableRow字段并不是您想要的查询类型的万能解决方案。我已向another SQL Fiddle添加了一些PARTITION BY策略示例:

select pid, firstName, lastName, dateOfBirth, obsName, obsValue, obsDate, 
      rowRank, CASE rowRank WHEN 1 THEN 1 ELSE 0 END AS countableRow,
      valueRank, CASE valueRank WHEN 1 THEN 1 ELSE 0 END AS valueCount,
      dobRank, CASE WHEN dobRank = 1 AND dateOfBirth IS NOT NULL THEN 1 ELSE 0 END AS dobCount
from 
(
select Person.pid, Person.firstName, Person.lastName, Person.dateOfBirth
      , Obs.obsName, Obs.obsValue, Obs.obsDate,
      ROW_NUMBER() OVER (PARTITION BY Person.pid, Person.firstName, Person.lastName, Person.dateOfBirth ORDER BY Obs.obsDate) AS rowRank,
      ROW_NUMBER() OVER (PARTITION BY Obs.obsName, Obs.obsValue ORDER BY Obs.obsDate) AS valueRank,
      ROW_Number() OVER (PARTITION BY Person.dateOfBirth ORDER BY Person.pid) AS dobRank
  from Person
    join Obs on Person.pId = Obs.pId
) rankedData

以免任何人误解我,认为这总是合适的,显然不是。这不是使用其他SQL查询获取特定答案的更好解决方案。它允许您做的是编码足够的信息,以便在单个结果集中的消费代码中简单地回答这些问题。这就是它可以派上用场的地方。

第二次编辑

由于您想知道如果比赛数据存储在多个地方是否可以这样做,答案绝对是。我修改了之前的SQL Fiddle中的代码,现在是available in a new one

select pid, firstName, lastName, dateOfBirth, obsName, obsValue, obsDate, 
      rowRank, CASE rowRank WHEN 1 THEN 1 ELSE 0 END AS countableRow,
      valueRank, CASE valueRank WHEN 1 THEN 1 ELSE 0 END AS valueCount,
      dobRank, CASE WHEN dobRank = 1 AND dateOfBirth IS NOT NULL THEN 1 ELSE 0 END AS dobCount,
      raceRank, CASE WHEN raceRank = 1 AND (race IS NOT NULL OR obsName = 'RACE') THEN 1 ELSE 0 END AS raceCount
from 
(
select Person.pid, Person.firstName, Person.lastName, Person.dateOfBirth, Person.[race]
      , Obs.obsName, Obs.obsValue, Obs.obsDate,
      ROW_NUMBER() OVER (PARTITION BY Person.pid, Person.firstName, Person.lastName, Person.dateOfBirth ORDER BY Obs.obsDate) AS rowRank,
      ROW_NUMBER() OVER (PARTITION BY Obs.obsName, Obs.obsValue ORDER BY Obs.obsDate) AS valueRank,
      ROW_NUMBER() OVER (PARTITION BY Person.dateOfBirth ORDER BY Person.pid) AS dobRank,
      ROW_NUMBER() OVER (PARTITION BY ISNULL(Person.race, CASE Obs.obsName WHEN 'RACE' THEN Obs.obsValue ELSE NULL END) ORDER BY Person.pid) AS raceRank
  from Person
    left join Obs on Person.pId = Obs.pId
) rankedData

正如您所看到的,在新的小提琴中,这恰当地将Races的数量计为3,其中2在Obs表中,第三个在Person表中。诀窍是PARTITION BY可以包含表达式,而不仅仅是原始列输出。请注意,我在这里将连接更改为左连接,并且我们需要使用CASE仅包含obsValue WHERE obsName是'RACE'。它有点复杂,但并非如此复杂,它可以优雅地处理相当复杂的情况。

答案 1 :(得分:1)

事实证明,Jeroen指向RunningValue的指针比我想象的更具针对性。我能够通过以下代码获得我想要的结果:

=RunningValue(Iif(Not IsNothing(Fields!DATEOFBIRTH.Value)
        , Fields!PATIENTID.Value
        , Nothing)
    , CountDistinct
    , Nothing
    )

特别感谢Dominic P,我将在下次记住他的技术。

答案 2 :(得分:0)

除非他们报告不同的DOB,否则每位患者只会记录一条记录:

SELECT P.FOO, 
    P.BAR, 
    (etc.), 
    O.DOB
FROM Patients P
INNER JOIN Observations O
    ON P.PatientID = O.PatientID
GROUP BY P.FOO, P.BAR, (P.etc), O.DOB