2014-01-24 4 views
1

У меня есть две таблицы register и att_bottom, и я хочу отображать только студентов в определенном здании, которые были опозданы на основе сегодняшней даты с периодами, разделенными запятой. Это способ отображения данных при соединении обеих таблиц:Объяснение значений строк sql server 2008 r2

Student ID | Building | Period | Grade 

    12345   2   1  11   
    12345   2   5  11 
    2   1  12 

Я хочу это:

Student ID | <u>Building | Period | Grade 

12345   2   1,5  11 
    2   1  12 

Это мой запрос:

select r.STUDENT_ID, 
     r.BUILDING , 
     (select ab.attendancePeriod + ',' 
     from att_bottom ab 
     where ab.STUDENT_ID = r.student_id 
     and ab.building = '2' 
     and ab.attendance_c ='T' 
     and ab.SCHOOL_YEAR =2014 
     CONVERT(date,ab.attendance_date,102) = convert(date,getdate(),102) 
     FOR XML PATH ('')) AS PERIODS, 
     r.GRADE 
     FROM register r 
    where r.CURRENT_STATUS = 'A' 
    and r.BUILDING ='2' 

Я получаю все студенты в здании 2 и даже если у них нет attedance_c of T; значение NULL для периодов его извлечения:

Student ID | Building | Period | Grade 

12345   2  1 , 5 11 
    2  1 ,  12 
95687   2  NULL  09 
78417   2  NULL  10 
20357   2  NULL  11 

Я попытался and ab.attendancePeriod is Not NULL и я до сих пор получить тот же результат.

Любые мысли?

+0

Что 'DataType' вы используете для вашего Столбец «Период» ?? – prograshid

+0

Я получаю три строки с этим запросом, а не 5 (после исправления синтаксических ошибок). Можете ли вы дважды проверить, как вы получаете эти результаты? (например, откуда пришли 95687, 78417 и т. д. - они просто существуют в регистре, но не в att_bottom?) –

+0

Номера представляют собой случайные идентификаторы, которые я использовал для иллюстрации проблемы. – user1308665

ответ

0

Внешний запрос не прослушивает никаких фильтров в подзапросе; он вернет NULL для любых строк, которые не соответствуют условиям соединения. Вам нужно фильтровать по-другому. Вот один из способов (это также исключает странствующий Запятая, и избегает сравнения дат путем преобразования их подороже в строки):

;WITH x AS 
(
    SELECT DISTINCT s = r.Student_ID, r.building, 
    p = ab.attendancePeriod, r.grade 
    FROM dbo.Register AS r 
    INNER JOIN dbo.att_bottom AS ab 
    ON r.Student_ID = ab.Student_ID 
    AND r.building = ab.building 
    WHERE ab.building = '2' 
    AND ab.attendance_c = 'T' 
    AND ab.SCHOOL_YEAR = 2014 
    AND ab.attendance_date >= CONVERT(DATE, GETDATE()) 
    AND ab.attendance_date < DATEADD(DAY, 1, CONVERT(DATE, GETDATE())) 
    AND r.building = '2' 
    AND r.CURRENT_STATUS = 'A' 
) 
SELECT DISTINCT 
    [Student ID] = x.s, 
    x.building, 
    Period = STUFF((SELECT ',' + x2.p FROM x AS x2 WHERE x2.s = x.s 
    FOR XML PATH(''), TYPE).value('.','nvarchar(max)'),1,1,''), 
    x.grade 
FROM x; 

Другой способ:

SELECT DISTINCT 
    r.Student_ID, 
    r.building, 
    Period = STUFF(b.p.value('.', 'nvarchar(max)'),1,1,''), 
    r.grade 
FROM dbo.Register AS r 
CROSS APPLY 
(
    SELECT p = ',' + ab.attendancePeriod 
    FROM dbo.att_bottom AS ab 
    WHERE ab.building = '2' 
    AND ab.attendance_c = 'T' 
    AND ab.SCHOOL_YEAR = 2014 
    AND ab.attendance_date >= CONVERT(DATE, GETDATE()) 
    AND ab.attendance_date < DATEADD(DAY, 1, CONVERT(DATE, GETDATE())) 
    AND ab.student_id = r.student_id 
    AND ab.building = r.building 
    FOR XML PATH(''),TYPE 
) AS b(p) 
WHERE b.p IS NOT NULL 
    AND r.building = '2' 
    AND r.CURRENT_STATUS = 'A'; 
+0

Спасибо, что сработало отлично! – user1308665

0

Переместить AS PERIODS, чтобы выбрать внутреннее соединение с r.

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