3

我当前正在处理的查询返回了所需的结果,但问题是我必须为要添加的每个额外列创建一个具有不同 TaskCounters 的附加连接(这当然不是一个理性的决定)。

该查询应该在 SQLServer 以及 Access DB 上运行,因此我不需要任何访问中不支持的特殊功能(如 Pivot、CTE 等)。我需要修改该查询,以便尽可能减少连接数。

tblConsultations 是主表,其中根据访问类型记录特定儿童的条目(即,如果我们有 4 次访问,我们有 4 个咨询条目)。结果列应显示这 4 次访问的值,如果访问没有值,则显示 NULL。

我想消除对同一个表的额外连接的需要,我必须为每个额外的列添加这些连接

查询如下:

SELECT Cast(SUBSTRING(tc2.ChildCounter, 7, LEN(tc2.ChildCounter)) AS NUMERIC) AS pkChildID
,tc2.VisitType
,tblQuitOffered.Result AS KWA_QuitOffered
,tblQuitReferral.Result As KWA_QuitReferral
FROM tblConsultations tc2
INNER JOIN tblChild tc ON tc2.ChildCounter = tc.ChildCounter
LEFT  JOIN tblDelivery td ON td.ChildCounter = tc.ChildCounter
LEFT JOIN (
SELECT ttr.ResultCounter
    ,ttr.ChildCounter
    ,tkt.VisitType
    ,ttr.Result
    ,ttr.TaskCounter
FROM tblTaskResults ttr
INNER JOIN tlkpKeyTasks tkt ON tkt.TaskCounter = ttr.TaskCounter
    AND tkt.TaskCounter IN (
        '001410'
        ,'001463'
        ,'001431'
        )

) AS tblQuitOffered ON tc2.VisitType = tblQuitOffered.VisitType
AND tblQuitOffered.ChildCounter = tc2.ChildCounter
LEFT JOIN (
SELECT  ttr.ChildCounter
    ,tkt.VisitType
    ,ttr.Result
FROM tblTaskResults ttr
INNER JOIN tlkpKeyTasks tkt ON tkt.TaskCounter = ttr.TaskCounter
    AND tkt.TaskCounter IN (
        '001411'
        ,'001464'
        ,'001432'
        )
) AS tblQuitReferral ON tc2.VisitType = tblQuitReferral.VisitType
AND tblQuitReferral.ChildCounter = tc2.ChildCounter
WHERE tc2.VisitType in (1, 2, 3, 4)
AND tc2.ConsDate BETWEEN '20130127' and '20130228'
ORDER BY tc2.ChildCounter,tc2.VisitType

结果如下:

pkChildID   VisitType     KWA_QuitOffered   KWA_QuitReferral
2224        1             No                No
2224        3             NULL              NULL
2224        4             NULL              NULL
2225        1             No                Yes
2225        2             Yes               Yes
2225        3             Yes               Yes
2225        4             NULL              NULL
4

3 回答 3

1

如果我理解正确,您可以TaskCounter在单个派生表中包含所需的所有值,然后使用CASE语句来分配列值:

SELECT Cast(SUBSTRING(tc2.ChildCounter, 7, LEN(tc2.ChildCounter)) 
            AS NUMERIC) AS pkChildID
      ,tc2.VisitType

      ,MAX(CASE WHEN tktResults.TaskCounter IN (
                '001410'
               ,'001463'
               ,'001431'
               ) THEN tktResults.Result END
          ) AS KWA_QuitOffered

      ,MAX(CASE WHEN tktResults.TaskCounter IN (
                '001411'
               ,'001464'
               ,'001432'
               ) THEN tktResults.Result END
          ) AS KWA_QuitReferral

FROM  tblConsultations tc2
INNER JOIN tblChild tc 
  ON  tc2.ChildCounter = tc.ChildCounter
LEFT  JOIN tblDelivery td
  ON  td.ChildCounter = tc.ChildCounter

LEFT JOIN (
   SELECT ttr.ResultCounter
         ,ttr.ChildCounter
         ,tkt.VisitType
         ,ttr.Result
         ,ttr.TaskCounter
   FROM tblTaskResults ttr
   INNER JOIN tlkpKeyTasks tkt 
   ON tkt.TaskCounter = ttr.TaskCounter
       AND tkt.TaskCounter IN (
            '001410'
           ,'001463'
           ,'001431'
           ,'001411'
           ,'001464'
           ,'001432'
           )
   ) AS tktResults 
ON     tktResults.VisitType    = tc2.VisitType
   AND tktResults.ChildCounter = tc2.ChildCounter

WHERE tc2.VisitType in (1, 2, 3, 4)
  AND tc2.ConsDate BETWEEN '20130127' and '20130228'
GROUP BY 1, 2
ORDER BY tc2.ChildCounter,tc2.VisitType

事实上,您实际上并不需要将其设为派生表(LEFT JOIN (...)部分),但我假设您出于性能原因这样做。当您根据 的不同值添加列时TaskCounter,只需将它们添加到连接条件即可。

编辑:修改为使用GROUP BY带有函数的子句通过andMAX返回唯一行。pkChildIDVisitType

我在GROUP BY子句中使用“有序列表”样式;如果不支持,您可能需要像这样指定它:

GROUP BY Cast(SUBSTRING(tc2.ChildCounter, 7, LEN(tc2.ChildCounter)) AS NUMERIC)
        ,tc2.VisitType

我还注意到您正在按不属于 SELECT 子句的列进行排序。我不知道为什么,但完好无损。

于 2013-04-14T15:07:39.463 回答
1

我发布了一个答案,有些人认为就像 BellevueBob 发布的那样。

我认为您可以使用嵌套 iif() 而不是“case when”

于 2013-04-14T15:32:58.903 回答
0

通常在 SQL 中创建一个新表可以解决问题。让我们称之为coderesolve。

它看起来像这样:

Code    QuitOffered    QuitReferral
001410  1              Null
001462  1              Null
001431  1              Null
001411  Null           1
001464  Null           1
001432  Null           1

您可以为要执行的每个“新”连接添加更多列。

然后你的代码看起来像这样

SELECT 
  Cast(SUBSTRING(tc2.ChildCounter, 7, LEN(tc2.ChildCounter)) AS NUMERIC) 
     AS pkChildID
  ,tc2.VisitType
  ,ttr.Result AS KWA_QuitOffered
  ,ttr.Result As KWA_QuitReferral
FROM tblConsultations tc2
INNER JOIN tblChild tc ON tc2.ChildCounter = tc.ChildCounter
LEFT  JOIN tblDelivery td ON td.ChildCounter = tc.ChildCounter
JOIN  tblTaskResults ttr on tc2.VisitType = ttr.VisitType
JOIN  tlkpKeyTasks tkt ON tkt.TaskCounter = ttr.TaskCounter
JOIN  coderesolve cr on cr.code = tkt.TaskCounter 
   AND COALESCE(cr.QuitOffered,cr.QuitReferral,0) = 1
WHERE tc2.VisitType in (1, 2, 3, 4)
AND tc2.ConsDate BETWEEN '20130127' and '20130228'
ORDER BY tc2.ChildCounter,tc2.VisitType

这应该适用于 Access。但是 Access 很有趣,所以没有任何承诺。

另请注意,我假设您的代码是互斥的(在 coderesolve 连接上只给您一个行结果),如果不是这种情况,您可能必须将其分解为子查询并进行分组或不同-- 取决于您的型号。

于 2013-04-15T04:07:04.957 回答