2013-04-14 4 views
3

Запрос, на котором я работаю в настоящий момент, возвращает желаемые результаты, но проблема в том, что мне нужно создать дополнительное соединение с различными TaskCounters для каждого дополнительного столбца, который я хочу добавить (что, конечно, не является рациональным решением).SQL Server Join

Запрос должен выполняться на SQLServer, а также в базе данных доступа, поэтому мне не нужны никакие специальные функции (например, Pivot, CTE и т. Д.), Которые не поддерживаются при доступе. Мне нужно пересмотреть этот запрос, чтобы количество соединений было уменьшено настолько, насколько это возможно.

tblКонсультации - это основная таблица, в которой запись для конкретного ребенка записывается в зависимости от типа посещения (т. Е. Если у нас есть 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 
+2

Я не думаю, что вы найдете один удовлетворительный ответ, который будет работать как с SQL Server, так и с MS Access. Как упоминалось в bluefeet, сам синтаксис SQL отличается. Возможно, вам понадобятся разные решения для каждой среды. – BellevueBob

+0

@BellevueBob Я не согласен, похоже, что нужен AMS - это просто предложение GROUP BY. Но для меня загадка заключается в использовании TaskCounter при определении QuitOffered и QuitReferral. –

+0

@BellevueBob - Кажется, я нашел ответ: D – Hogan

ответ

1

Если я правильно понимаю, вы можете включать в себя все TaskCounter значения, которые вы хотите в качестве Ingle производная таблица, а затем использовать 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, просто добавьте их в условие соединения.

EDIT: После доработки использовать GROUP BY пункт с MAX функцией для возврата уникальных строк по pkChildID и VisitType.

Я использую стиль «упорядоченного списка» в предложении GROUP BY; если это не поддерживается, возможно, потребуется указать это следующим образом:

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

Я также заметил, вы сортировку по столбцу, который не является частью ЗЕЬЕСТА. Я не уверен, почему, но оставил его нетронутым.

+0

В Ms Access нет 'CASE'. – Taryn

+0

@bluefeet По-видимому, нет; но я могу использовать VBA. Я пропустил часть о переносном решении, которое включало MS Access. Не используйте Access для самой «реальной» работы. – BellevueBob

+0

Трудная вещь - переносимость между сервером sql и ms доступом, к сожалению, они не имеют одинакового синтаксиса, как с функциями, так и с JOIN. MS Access требует скобок вокруг нескольких соединений таблицы. – Taryn

1

Я публиковал ответ, и некоторые думают, что опубликовал BellevueBob.

Я думаю, что вы можете использовать вложенные IIF() 's вместо „случае, когда“

+0

Веб-поиск также показал мне функцию «SWITCH», которая также может работать для Access, но, увы, я не думаю, что либо работало бы на SQL Server. – BellevueBob

+0

В зависимости от того, какая версия SQL Server 'IIF' может не поддерживаться. Он стал доступен в SQL Server 2012. – Taryn

+0

ooo Я вижу .. Вы хотите что-то, что работает как с SQL, так и с Ms Access ... Я прав, BellevueBob ... – Fuad

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. Но доступ забавный, поэтому никаких обещаний.

Другое примечание. Я предполагаю, что ваши коды являются взаимоисключающими (что дает вам только один результат строки для объединения coderesolve), если это не так, вам может потребоваться разбить его на подзапрос и выполнить группировка или отдельный - зависит от вашей модели.