Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从另一个结果集中提取结果_Sql_Sql Server_Sql Server 2012_Resultset - Fatal编程技术网

Sql 从另一个结果集中提取结果

Sql 从另一个结果集中提取结果,sql,sql-server,sql-server-2012,resultset,Sql,Sql Server,Sql Server 2012,Resultset,我正在做一个查询,我需要从某个诊所提取吸烟或使用某种烟草的所有患者的名单。然后,我需要列出一份清单,列出在给定时间范围内接受过戒烟咨询的任何患者 我想我做得对,但我不确定。前端系统是这样的,我们经常以不准确的数据结束(甚至不让我开始)。当我以这种方式运行查询时,我得到一个数字,我很确定这个数字太低了,但我不确定这是否只是数据问题,或者我的查询是否有问题。这是我得到的 首先,这是我查找所有烟草用户的查询。“状态”列表示使用的类型——您将在这里看到,我过滤掉了3、4和6,它们代表“以前的用户”、“从

我正在做一个查询,我需要从某个诊所提取吸烟或使用某种烟草的所有患者的名单。然后,我需要列出一份清单,列出在给定时间范围内接受过戒烟咨询的任何患者

我想我做得对,但我不确定。前端系统是这样的,我们经常以不准确的数据结束(甚至不让我开始)。当我以这种方式运行查询时,我得到一个数字,我很确定这个数字太低了,但我不确定这是否只是数据问题,或者我的查询是否有问题。这是我得到的

首先,这是我查找所有烟草用户的查询。“状态”列表示使用的类型——您将在这里看到,我过滤掉了3、4和6,它们代表“以前的用户”、“从未使用过”和“未知”(我只是查看确定当前正在使用烟草的人——如果适用,这些条目会在每次患者就诊时更新)

这个查询给了我3000多个结果,考虑到诊所的总患者人数,这似乎是正确的

现在,我需要从该结果集中抽取2016年1月1日至2016年6月30日期间接受过戒烟咨询(作为程序代码输入)-我将该字段添加到选择列表中)的所有人。以下是我所拥有的:

SELECT DISTINCT sh.PatientID, vi.ProcedureCode, pd.Physician, vi.VisitDate

FROM
    (SELECT DISTINCT sh.PatientID, sh.Description, sh.Category, sh.Status, 
     pd.Physician, vi.VisitDate, vi.ProcedureCode

     FROM SocialHistory sh JOIN PatientDemographic pd ON sh.PatientID = pd.PatientID 
     JOIN VisitInfo vi ON vi.PatientID = pd.PatientID

     WHERE sh.Description LIKE '%tobacco%'
     AND sh.Status != 3
     AND sh.Status != 4
     AND sh.Status != 6

    ) VisitInfo

WHERE vi.ProcedureCode IN ('counseling1','counseling2','counseling3')

AND VisitDate BETWEEN '01/01/2016' AND '06/30/2016'

我只得到了大约190个结果,考虑到3000多名烟草用户,这似乎真的很低。但它可能是准确的。我只是想确保我的查询是正确的。嵌套的
SELECT
语句结构是否正确?

这里是另一种编写查询的方法,它可读性更强,并且不需要子选择

SELECT DISTINCT
   sh.PatientID
   ,vi.ProcedureCode
   ,pd.Physician
   ,vi.VisitDate
 FROM
   SocialHistory sh
   INNER JOIN PatientDemographic pd
   ON sh.PatientID = pd.PatientID 
   INNER JOIN VisitInfo vi
   ON vi.PatientID = pd.PatientID
   AND vi.ProcedureCode IN ('counseling1','counseling2','counseling3')
   AND VisitDate BETWEEN '01/01/2016' AND '06/30/2016'
 WHERE
   sh.Description LIKE '%tobacco%'
   AND sh.Status NOT IN (3,4,6)

这6个月更有可能是你的记录数量减少的原因,扩大时间范围或对这一行进行评论,以测试你的结果集是什么,看看它是否符合你认为的结果应该是什么。如果是这样的话,那么你就知道这是6个月了。

只是一个改进编码的建议。计算机擅长记忆事物的代码;人们不是。必须为“前吸烟者”输入“2”,或为“明尼苏达州的生活”输入“5”,这是非常荒谬的。应该有一个将代码与实际状态关联起来的表,以便您可以在需要时查找。或者使用短字符串代码,如“前吸烟者”的“FSM”或“明尼苏达州生活”的“LMN”:诸如此类。

我看不出您的查询有任何错误,但正如所指出的,您不需要子查询。我会这样写

SELECT DISTINCT sh.PatientID, vi.ProcedureCode, pd.Physician, vi.VisitDate
FROM SocialHistory as sh
JOIN PatientDemographic as pd ON sh.PatientID = pd.PatientID 
JOIN VisitInfo as vi          ON vi.PatientID = pd.PatientID
WHERE
    sh.Description LIKE '%tobacco%'
AND sh.Status not in (3, 4, 6)
AND vi.ProcedureCode IN ('counseling1','counseling2','counseling3')
AND VisitDate BETWEEN '01/01/2016' AND '06/30/2016'
因为它使用
JOIN
仅用于匹配条件,而
WHERE
用于限制。(我相信SQL Server将为这两个查询显示相同的查询计划,也可能为您的查询显示相同的查询计划。)

当您确实使用子查询时,请避免在子查询中使用
DISTINCT
,除非它在语义上很重要。在您的查询中,您得到不同的患者,然后是一组不同的患者。只需要一个。查询计划器应该找到一个快捷方式,但可能找不到,任何阅读您的SQL的人都有那么多杂音要看

至于故障排除,您可以尝试以下方法来查看您正在处理的问题:

select   count(distinct PatientID) as N, M, Y
from (
    SELECT   sh.PatientID, vi.ProcedureCode, pd.Physician, vi.VisitDate
           , year(vi.VisitDate) as Y
           , month(vi.VisitDate) as M
    FROM SocialHistory as sh
    JOIN PatientDemographic as pd ON sh.PatientID = pd.PatientID 
    JOIN VisitInfo as vi          ON vi.PatientID = pd.PatientID
    WHERE
        sh.Description LIKE '%tobacco%'
    AND sh.Status not in (3, 4, 6)
    AND vi.ProcedureCode IN ('counseling1','counseling2','counseling3')
    --- VisitDate BETWEEN '01/01/2016' AND '06/30/2016'
) as V
group by M, Y

如果这太多了,请只按Y分组,或者可以
其中M=1

这里,试试下面。由于您只需要接受咨询的患者,因此将返回患者和提供者数据。如果您想让未接受咨询的患者也接受咨询,只需在
IsCounselledStatus>0
部分进行注释,所有带有“0”的患者都未接受咨询

declare @StartDate datetime = '1/1/'+cast(datepart(YEAR,getdate()) as varchar(4));
declare @EndDate datetime = '6/30/'+cast(datepart(YEAR,getdate()) as varchar(4));

;with cte as
(
    select sh.PatientID, sh.Description, sh.Category, sh.Status, pd.Physician, vi.VisitDate, vi.ProcedureCode,
        case when (sh. status not in (3,4,6) 
                    and sh.Description LIKE '%tobacco%' 
                    and VisitDate BETWEEN @StartDate AND @EndDate
                    and vi.ProcedureCode IN ('counseling1','counseling2','counseling3')
                   ) then 1 else 0 end as IsCounselled
    from SocialHistory sh JOIN PatientDemographic pd ON sh.PatientID = pd.PatientID 
    join VisitInfo vi ON vi.PatientID = pd.PatientID 
)
select PatientID, Physician, sum(IsCounselled) IsCounselledStatus
from cte c
where IsCounselledStatus > 0
group by PatientID, Physician

此外,正如David所指出的,如果你在表格中有你的参考项目会更好。

你的
和访问日期在'01/01/2016'和'06/30/2016'之间。
仅涵盖6个月。顺便说一句:避免特定文化的日期格式。我们最好不分离,如
20160101
或类似ODBC的
{d'2016-01-01'}
或ISO 8601!不太清楚为什么在这里有子查询。而且,不需要像这样嵌套的distinct。如果在外部查询中不需要列,则不应在子查询中选择它们。sh.说明,sh.类别,sh.状态都可能被删除,因为它们没有被使用。是的,我只是在看6个月的时间框架。我的印象是,我需要子查询来确保我从第一个结果集中提取结果。基本上我说的是“从所有患者中选择烟草使用者,然后从烟草使用者中选择咨询患者”。当然,我想我可以从所有患者中选择咨询患者,但关键是要知道哪些使用者接受过咨询,哪些没有。我想我需要先看看用户的总数。有一张表。SocialHistory实际上是一个视图,Status字段来源于一个SubstanceUse表,该表显示了每个代码代表的内容。Bruce查找表是有效的,假定EJF没有这些表。但是,即使您编写类似的代码,您也可能只是从查找表中获取所需的代码并使用ID。。。还要非常小心地将业务逻辑注入到一个短字符串中,以代替可能很快就会搞乱的查找表!是的,我想知道6个月是否是问题所在。如果我完全去掉日期范围,它只有大约990个,这似乎仍然很低(只有烟草使用者总数的1/3左右)。仍然不确定这是否准确,但根据所选的时间框架,肯定会有差异。1/3接受戒烟咨询的患者对我来说一点也不低,尤其是如果他们是必须寻求咨询的患者。即使它被提供力量,它也看不到低。。。。。。。。。但我不在医疗机构所以。。。另一件事,你可能要考虑的是,如果你有所有的程序代码,如果你缺少一个,这可能是一个原因,结果是低。是的,这是我的问题-我只是
declare @StartDate datetime = '1/1/'+cast(datepart(YEAR,getdate()) as varchar(4));
declare @EndDate datetime = '6/30/'+cast(datepart(YEAR,getdate()) as varchar(4));

;with cte as
(
    select sh.PatientID, sh.Description, sh.Category, sh.Status, pd.Physician, vi.VisitDate, vi.ProcedureCode,
        case when (sh. status not in (3,4,6) 
                    and sh.Description LIKE '%tobacco%' 
                    and VisitDate BETWEEN @StartDate AND @EndDate
                    and vi.ProcedureCode IN ('counseling1','counseling2','counseling3')
                   ) then 1 else 0 end as IsCounselled
    from SocialHistory sh JOIN PatientDemographic pd ON sh.PatientID = pd.PatientID 
    join VisitInfo vi ON vi.PatientID = pd.PatientID 
)
select PatientID, Physician, sum(IsCounselled) IsCounselledStatus
from cte c
where IsCounselledStatus > 0
group by PatientID, Physician