2014-10-15 6 views
3

Я использую SQL 2008 и пытаюсь запустить запрос, где я проверяю значения в нескольких столбцах и объединяю результаты в новый столбец. Из моих исследований, похоже, мне нужно использовать CONCAT, чтобы сделать это, но я не могу понять, где разместить это в своем запросе. Кроме того, первая проблема, с которой я столкнулась, заключается в том, что мой запрос, кажется, возвращает неточные результаты для всего.SQL CASE Неожиданные результаты

У меня есть таблица «Shifts», которая содержит EmplID вместе с разными столбцами для каждого дня недели (тип бит) и раз. Такие, как:

ShiftsID EmplID M Tu W Th F Sa Su StartTime EndTime 
2001  1001 0 0 0 0 0 0 1 8:30:00  15:00:00 
2002  1001 1 1 1 1 1 0 0 7:00:00  15:00:00 

стол Мой персонал выглядит примерно следующее:

LegalName EmployeeID 
Doe, John 1001 

Мой запрос выглядит следующим образом

SELECT Shifts.ShiftsID, 
     X.WorkingDays, 
     Personnel.EmployeeID, 
     Personnel.FullName, 
     Shifts.Start, 
     Shifts.End 
FROM (SELECT *, 
       CASE 
       WHEN Shifts.M = '1' THEN 'M' 
       WHEN Shifts.Tu = '1'THEN 'Tu' 
       WHEN Shifts.W = '1' THEN 'W' 
       WHEN Shifts.Th = '1' THEN 'Th' 
       WHEN Shifts.F = '1' THEN 'F' 
       WHEN Shifts.Sa = '1' THEN 'Sa' 
       WHEN Shifts.Su = '1' THEN 'Su' 
       ELSE NULL 
       END AS WorkingDays 
     FROM Shifts 
     WHERE EmplID = '1001') X, 
     Personnel 
     INNER JOIN Shifts 
       ON Personnel.EmployeeID = Shifts.EmplID 
WHERE (Personnel.EmployeeID = '1001') 
     AND (X.WorkingDays != '') 

Результаты этого запроса являются:

ShiftsID WorkingDays EmployeeID LegalName StartTime EndTime 
2001  Su   1001  Doe, John 8:30:00  15:00:00 
2002  Su   1001  Doe, John 7:00:00  15:00:00 
2001  M   1001  Doe, John 8:30:00  15:00:00 
2002  M   1001  Doe, John 7:00:00  15:00:00 

То, что я на самом деле я нуждаясь, чтобы показать будет что-то вроде следующего:

ShiftsID WorkingDays EmployeeID LegalName StartTime EndTime 
2001  Su   1001  Doe, John 8:30:00  15:00:00 
2002  MTuWThF  1001  Doe, John 7:00:00  15:00:00 

Итак, что я делаю неправильно с моим текущим запросом Thats дает мне неожиданные результаты? И где я помещаю CONCAT, чтобы получить действительные рабочие конкатенации по мере необходимости? Или есть вариант, отличный от CONCAT, который я должен использовать?

+0

'CONCAT' - это только SQL Server 2012. Оператор '+' аналогичен предыдущим версиям. Похоже, вы забыли добавить условие соединения для вашей производной таблицы 'X', чтобы получить кросс-соединение. –

+0

Похоже, вы переходите данные на 'ShiftID' между' 2001' и '2002' и получаете смешанные результаты – Tak

+0

Вы не получаете неожиданных результатов, JOIN с дубликатами или более приведет к ситуации CROSS JOIN, поэтому для данных данных сначала WorkDays - это Su, поэтому он будет повторяться дважды, а затем M и т. Д. Что касается того, как сгруппировать в sql-сервер, вы можете использовать FOR XML PATH – Mihai

ответ

2

Я думаю, что это должно работать SQL Fiddle

SELECT * 
FROM (SELECT Shifts.ShiftsID, 
       ISNULL((SELECT 'M' WHERE Shifts.M = '1'), '') 
       + ISNULL((SELECT 'Tu' WHERE Shifts.Tu = '1'), '') 
       + ISNULL((SELECT 'W' WHERE Shifts.W = '1'), '') 
       + ISNULL((SELECT 'Th' WHERE Shifts.Th = '1'), '') 
       + ISNULL((SELECT 'F' WHERE Shifts.F = '1'), '') 
       + ISNULL((SELECT 'Sa' WHERE Shifts.Sa = '1'), '') 
       + ISNULL((SELECT 'Su' WHERE Shifts.Su = '1'), '') AS WorkingDays, 
       Personnel.EmployeeID, 
       Personnel.LegalName, 
       StartTime, 
       EndTime 
     FROM Shifts 
       INNER JOIN Personnel 
         ON Personnel.EmployeeID = Shifts.EmplID 
     WHERE Personnel.EmployeeID = '1001') T 
WHERE WorkingDays <> '' 

Это должно сцепить дни. Используйте ISNULL ((SELECT ...), ''), хотя SQL Server 2008 не поддерживает инструкцию IIF.

+0

@Martin Smith. Да, спасибо. Я изменил код. – Barry

+0

То, что мне нужно! Большое спасибо. – aantiix

2

Это кажется довольно простым - если только я не упустил что-то. Я использовал выражение CASE, чтобы создать последовательность дней, когда сотрудник работает.

Этот запрос, как представляется, дает желаемые результаты.

SELECT * 

    -- string representing all working days. 
    ,CASE WHEN Shifts.M = '1' THEN 'M' ELSE '' END + 
     CASE WHEN Shifts.Tu = '1' THEN 'Tu' ELSE '' END + 
     CASE WHEN Shifts.W = '1' THEN 'W' ELSE '' END + 
     CASE WHEN Shifts.Th = '1' THEN 'Th' ELSE '' END + 
     CASE WHEN Shifts.F = '1' THEN 'F' ELSE '' END + 
     CASE WHEN Shifts.Sa = '1' THEN 'Sa' ELSE '' END + 
     CASE WHEN Shifts.Su = '1' THEN 'Su' ELSE '' END AS [WorkingDays] 

FROM 
    #Shifts AS Shifts 
    -- INNER JOIN Personnel ON Personnel.EmployeeID=Shifts.EmplID 
WHERE EmplID = '1001' 
    -- only show shifts that contain one or more day? 
    AND (
     Shifts.M='1' OR 
     Shifts.Tu='1' OR 
     Shifts.W='1' OR 
     Shifts.Th='1' OR 
     Shifts.F='1' OR 
     Shifts.Sa='1' OR 
     Shifts.Su='1' 
    ); 
+1

Минус nitpick, но 'CASE' является * выражением *. Заявление в SQL было бы «SELECT», «UPDATE» и т. Д. – Ellesedil

+0

Исправлено, хороший улов. – laylarenee

Смежные вопросы