如何以复杂的方式使用案例

Posted

技术标签:

【中文标题】如何以复杂的方式使用案例【英文标题】:How use case in complex way 【发布时间】:2021-07-09 20:59:05 【问题描述】:

我有一个新案例要添加到我的查询中,它显着改变了我的 sql 的方式,并且可能需要案例语句,但我不确定如何将我现在想做的联合作为结合起来案例陈述。案例表和概念表非常大/慢,最好不要单独/两次加入它们。但是,新的查询部分不需要 #tempCMs、external_user_data 或 cm.first/lastName 或 cm.user_id。一个有 queueName,另一个没有。每个都有不同的主题。有没有人知道如何组合查询以避免两次命中慢表?

这是存储过程的旧部分:

SELECT distinct
 c.id
 ,uc.id
 ,cm.FIRSTNAME as CM_first
 ,cm.LASTNAME as CM_last
 ,cm.user_id as cm_userid
 ,c.person_id 
 ,eou.external_id--eou.external_id AS CM_ExternalUserId
 ,c.id+' '+' Query1' AS subject 
 ,emd.externalId externalPersonId 
 ,eou.system_id as externalSystemId
 ,'' --no queue passed for this area
FROM
    #tempCMs CM with (NOLOCK) 
    INNER JOIN dbo.CASES c with (NOLOCK)  ON CM.Personid=c.id
    INNER JOIN dbo.UM_CASE uc with (NOLOCK) ON uc.case_id=c.id 
    INNER JOIN dbo.LOS S WITH (NOLOCK) ON S.case_id =  UC.case_id 
    INNER JOIN dbo.LOS_EXTENSION SC WITH (NOLOCK) ON SC.los_id= S.id 
    INNER JOIN dbo.USER u with (NOLOCK) on u.id=cm.user_id --
    INNER JOIN dbo.PERSON op with (NOLOCK) on op.id=c.Person_id
    INNER JOIN dbo.U_MEMBER_CONCEPT MC ON MC.CID = op.cid 
    INNER JOIN dbo.EXTERNAL_USER_DATA eou with (NOLOCK) ON eou.user_id = cm.user_id --
    INNER JOIN dbo.EXTERNAL_MEMBER_DATA emd with (NOLOCK) ON emd.CID = op.cid
    WHERE     

        u.disable <> 1 --not disabled/inactive user

            AND
            --not external case manager
               (cm.firstname not like '%external%' and cm.lastname not like '%case manager%')

            AND 
            (
                C.ID in (SELECT case_id FROM #CASES where concept_id='501620')
            ) 

这是新的联合部分:

UNION
SELECT DISTINCT
 c.id
 ,uc.id
 ,''--cm.FIRSTNAME as CM_first --?
 ,''--cm.LASTNAME as CM_last --?
 ,''--cm.user_id as cm_userid --? 
 ,c.person_id 
 ,'' --not needed for this case
 ,c.id+' '+' Query2' AS subject 
 ,emd.externalId externalPersonId 
 ,''--not needed 
 ,'queueName' AS externalQueue --new admission for this case
FROM
    --#tempCMs CM with (NOLOCK) 
    dbo.CASES c with (NOLOCK)  
    INNER JOIN dbo.UM_CASE uc with (NOLOCK) ON uc.case_id=c.id 
    INNER JOIN dbo.LOS S WITH (NOLOCK) ON S.case_id =  UC.case_id 
    INNER JOIN dbo.LOS_EXTENSION SC WITH (NOLOCK) ON SC.los_id= S.id 
    --INNER JOIN dbo.USER u with (NOLOCK) on u.id=cm.user_id
    INNER JOIN dbo.PERSON op with (NOLOCK) on op.id=c.Person_id
    INNER JOIN dbo.U_MEMBER_CONCEPT MC with (NOLOCK) ON MC.CID = op.cid 
    --INNER JOIN dbo.EXTERNAL_USER_DATA eou with (NOLOCK) ON eou.user_id = cm.user_id --??don't need/cm
    INNER JOIN dbo.EXTERNAL_MEMBER_DATA emd with (NOLOCK) ON emd.CID = op.cid
    INNER JOIN dbo.UM_SERVICE sv (NOLOCK) ON sv.case_id =  uc.case_id --different here
    WHERE     
            (
                sv.diag_code in (SELECT * FROM dbo.T_CAE1350_diag_codes_Indicator)
            )
            AND --member not already handled
            (
                C.person_ID not in (select person_id from #tempCMs ) 
            )

这样的表设置:

CASES
id   person_id   

UM_CASE
case_id  

LOS
case_id  id

LOS_EXTENSION
los_id

Person
id    cid

U_MEMBER_CONCEPT
cid

EXTERNAL_USER_DATA
cid   user_id

EXERNAL_Member_data
cid

UM_SERVICE
case_id     diag_code

USER
id  first_name   last_name

CREATE TABLE #tempCMs
(
    CASEID VARCHAR(12),
    Person_id int,
    id VARCHAR(25),
    user_id int,
    LASTNAME VARCHAR(150),
    FIRSTNAME VARCHAR(150)
)

INSERT INTO #tempCMs(CASEID,Person_id, id, user_id, lastname, firstname)
SELECT case_id,person_id, id, ccv.user_id, u.LAST_NAME, u.FIRST_NAME
FROM dbo.CM_CASES_VIEW ccv
inner join dbo.USER u with (nolock) on ccv.user_id=u.id

CM_CASES_VIEW
user_id   person_id  case_id


SELECT DISTINCT C.ID AS CASE_ID
,mcv.concept_id
,mcv.STR_VALUE
INTO #CASES
FROM 
    dbo.CASES C 
    INNER JOIN dbo.UM_CASE UC (NOLOCK) ON  C.ID = UC.case_id                    
    INNER JOIN dbo.PERSON OP (NOLOCK) ON  C.person_id = OP.ID
    INNER JOIN dbo.U_MEMBER_CONCEPT MCV (NOLOCK) ON OP.CID = MCV.CID    

我不确定要在网上搜索什么来回答这个问题,因为它非常复杂。非常感谢您的任何想法!

**更新星期六...你怎么看?这是否可以很好地处理慢表,但将信息输入 cte 并稍后使用?

;with commonElement_cte as(
SELECT DISTINCT
     c.id
     ,uc.id as ucid
     ,uc.case_id
     ,c.person_id 
     ,c.id+' '+' Query2' AS subject 
     ,emd.externalId externalPersonId 
    FROM
        dbo.CASES c with (NOLOCK)  
        INNER JOIN dbo.UM_CASE uc with (NOLOCK) ON uc.case_id=c.id 
        INNER JOIN dbo.LOS S WITH (NOLOCK) ON S.case_id =  UC.case_id 
        INNER JOIN dbo.LOS_EXTENSION SC WITH (NOLOCK) ON SC.los_id= S.id 
        --INNER JOIN dbo.USER u with (NOLOCK) on u.id=cm.user_id
        INNER JOIN dbo.PERSON op with (NOLOCK) on op.id=c.Person_id
        INNER JOIN dbo.U_MEMBER_CONCEPT MC with (NOLOCK) ON MC.CID = op.cid 
        INNER JOIN dbo.EXTERNAL_MEMBER_DATA emd with (NOLOCK) ON emd.CID = op.cid
        
)  --common Element cte

select 

    SELECT distinct
     ce.id
     ,ce.ucid
     ,cm.FIRSTNAME as CM_first
     ,cm.LASTNAME as CM_last
     ,cm.user_id as cm_userid
     ,ce.person_id 
     ,ce.external_id--eou.external_id AS CM_ExternalUserId
     ,ce.id+' '+' Query1' AS subject 
     ,ce.externalId externalPersonId 
     ,eou.system_id as externalSystemId
     ,'' --no queue passed for this area
    FROM
        commonElement_cte ce
        INNER JOIN #tempCMs CM on CM.person_ID=ce.person_ID
        INNER JOIN dbo.USER u with (NOLOCK) on u.id=cm.user_id --
        INNER JOIN dbo.EXTERNAL_USER_DATA eou with (NOLOCK) ON eou.user_id = cm.user_id --
        WHERE     
    
            u.disable <> 1 --not disabled/inactive user
    
                AND
                --not external case manager
                   (cm.firstname not like '%external%' and cm.lastname not like '%case manager%')
    
                AND 
                (
                    ce.ID in (SELECT case_id FROM #CASES where concept_id='501620')
                ) 

Here's new union part:

    UNION
    SELECT DISTINCT
     ce.id
     ,ce.ucid
     ,''--cm.FIRSTNAME as CM_first --?
     ,''--cm.LASTNAME as CM_last --?
     ,''--cm.user_id as cm_userid --? 
     ,ce.person_id 
     ,'' --not needed for this case
     ,ce.id+' '+' Query2' AS subject 
     ,ce.externalId externalPersonId 
     ,''--not needed 
     ,'queueName' AS externalQueue --new admission for this case
    FROM
        commonElement_cte ce
        INNER JOIN dbo.UM_SERVICE sv (NOLOCK) ON sv.case_id =  ce.case_id --different here
        WHERE     
                (
                    sv.diag_code in (SELECT * FROM dbo.T_CAE1350_diag_codes_Indicator)
                )
                AND --member not already handled
                (
                    ce.person_ID not in (select person_id from #tempCMs ) 
                )

【问题讨论】:

#tempCMs CM with (NOLOCK) 仅此一项就告诉我,编写此代码的人并没有真正理解该提示。您的组织不应使用nolock 散布代码。 但是您在描述中使用 CASE 似乎将 TSQL 函数(这是一个标量表达式)与您的 CASE 业务实体混淆了。有用的建议需要更详细地了解您的架构和用法。也许您应该首先专注于创建一个正确且有效的查询,然后尝试对其进行优化? 抱歉错字。将案例表更改为案例...我重命名了一些表名以使其更清晰。请不要专注于 nolock ...专注于结合两个查询的问题。旧查询肯定有效。 如果旧查询运行,这意味着您没有将其复制到您的问题中...FROM #tempCMs CM with (NOLOCK) and CM.status in ('1','4') 会给出语法错误;你不能把and 放在那里。 我去掉了 1/4 部分。 【参考方案1】:

您是否检查了执行计划以了解减速的原因?

您似乎正在扫描 CASES 和 U_MEMBER_CONCEPT 各 3 次。一次填充#CASES,一次在您的每个查询中。这个怎么样:

SELECT DISTINCT C.ID AS CASE_ID
, uc.id
, mcv.concept_id
, mcv.STR_VALUE
, c.person_ID
, op.cid
INTO #CASES
FROM         dbo.CASES C 
  INNER JOIN dbo.UM_CASE UC           ON C.ID = UC.case_id                    
  INNER JOIN dbo.PERSON OP            ON C.person_id = OP.ID
  INNER JOIN dbo.U_MEMBER_CONCEPT MCV ON OP.CID = MCV.CID   

如果可能的话,我建议添加一个WHERE 子句。

SELECT distinct
  c.case_id
, c.id
, cm.FIRSTNAME as CM_first
, cm.LASTNAME as CM_last
, cm.user_id as cm_userid
, c.person_id 
, eou.external_id--eou.external_id AS CM_ExternalUserId
, c.id+' '+' Query1' AS subject 
, emd.externalId externalPersonId 
, eou.system_id as externalSystemId
, '' --no queue passed for this area
FROM #tempCMs CM
  INNER JOIN #CASES c ON CM.Personid=c.id
  --INNER JOIN dbo.UM_CASE uc with (NOLOCK) ON uc.case_id=c.id 
  INNER JOIN dbo.LOS S WITH (NOLOCK) ON S.case_id =  UC.case_id 
  INNER JOIN dbo.LOS_EXTENSION SC WITH (NOLOCK) ON SC.los_id= S.id 
  INNER JOIN dbo.USER u with (NOLOCK) on u.id=cm.user_id --
  --INNER JOIN dbo.PERSON op with (NOLOCK) on op.id=c.Person_id
  --INNER JOIN dbo.U_MEMBER_CONCEPT MC ON MC.CID = op.cid 
  INNER JOIN dbo.EXTERNAL_USER_DATA eou with (NOLOCK) ON eou.user_id = cm.user_id --
  INNER JOIN dbo.EXTERNAL_MEMBER_DATA emd with (NOLOCK) ON emd.CID = c.cid

WHERE u.disable <> 1 --not disabled/inactive user
  AND cm.firstname not like '%external%'
    and cm.lastname not like '%case manager%'
  AND C.concept_id='501620' 

UNION
SELECT DISTINCT
  c.case_id
, c.id
, ''--cm.FIRSTNAME as CM_first --?
, ''--cm.LASTNAME as CM_last --?
, ''--cm.user_id as cm_userid --? 
, c.person_id 
, '' --not needed for this case
, c.id+' '+' Query2' AS subject 
, emd.externalId externalPersonId 
, ''--not needed 
, 'queueName' AS externalQueue --new admission for this case

FROM         #CASES c
  --INNER JOIN dbo.UM_CASE uc with (NOLOCK) ON uc.case_id=c.id 
  INNER JOIN dbo.LOS S WITH (NOLOCK) ON S.case_id =  UC.case_id 
  INNER JOIN dbo.LOS_EXTENSION SC WITH (NOLOCK) ON SC.los_id= S.id 
  --INNER JOIN dbo.USER u with (NOLOCK) on u.id=cm.user_id
  --INNER JOIN dbo.PERSON op with (NOLOCK) on op.id=c.Person_id
  --INNER JOIN dbo.U_MEMBER_CONCEPT MC with (NOLOCK) ON MC.CID = op.cid 
  --INNER JOIN dbo.EXTERNAL_USER_DATA eou with (NOLOCK) ON eou.user_id = cm.user_id --??don't need/cm
  INNER JOIN dbo.EXTERNAL_MEMBER_DATA emd with (NOLOCK) ON emd.CID = c.cid
  INNER JOIN dbo.UM_SERVICE sv (NOLOCK) ON sv.case_id =  uc.case_id --different here

WHERE sv.diag_code in (SELECT * FROM dbo.T_CAE1350_diag_codes_Indicator)        --  It is very unlikely this will work.
  AND C.person_ID not in (select person_id from #tempCMs)

并且不要使用SELECT *。永远。

【讨论】:

谢谢!我喜欢这个主意!最好不要使用 select *.我也会尝试为 #cases 找到 where 子句。 :)

以上是关于如何以复杂的方式使用案例的主要内容,如果未能解决你的问题,请参考以下文章

oracle如何缩短复杂操作的案例

Samba服务权限配置案例

PowerBI复杂地图可视化MapBox

如何以编程方式计算图像的(相对)复杂度?

如何以简化的方式编写普罗米修斯复杂警报规则?

如何以干净且可维护的方式编写非常复杂的 SQL? [关闭]