2017-02-13 12 views
0

У меня проблема, когда я пытаюсь вытащить расписания из периодов для человека. Если у них есть запись, я получаю строку со своим именем и статусом расписания. Но если они не представили ни один из двух расписаний за определенный период времени, они вообще не отображаются в запросе (это означает, что они будут упущены, когда кто-то отправится с ними следить).Результат возврата SQL Server для строки, когда нет записи о соединенной таблице, где статья

Вот упрощенный пример запроса, который не возвращает ничего, как resource_id не имеет данных в period_end_date больше, чем где пределы оговорка:

SELECT time_status_id, last_name 
FROM dbo.wh_resource 
LEFT JOIN wh_time_report ON wh_time_report.creator_resource_id = wh_resource.resource_id 
WHERE wh_resource.resource_id = '31100670' 
AND period_end_date >= '2017-01-29' 
ORDER BY last_name 

Я обнаружил, что делает его (period_end_date >= '2017-01-29' OR period_end_date IS NULL) не будет работать, так как они вошли данные в прошлом (если бы они никогда не были, это бы их подтянуть).

Есть ли способ поставить простой 0, если не было данных, найденных из-за period_end_date? Я смотрел СЛУЧАЯ ГДЕ, но никуда не уходил.

Я бы скорее получил time_status_id из 0 и имя человека, если у них нет записи, более новой, чем то, что искали. Возможно ли это достаточно просто?

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

SELECT wh_resource.resource_id, last_name, first_name, narrative_full_name, department_name, 
ISNULL(MAX(CASE WHEN wh_time_report.period_end_date = '2017-02-04' THEN time_status_id END),0) as timesheet_status1, 
SUM(CASE WHEN date_worked >= '2017-01-29' AND date_worked <= '2017-02-04' THEN ROUND(wh_time_subitem.hours_worked,2) END) as hours_total1, 
SUM(CASE WHEN date_worked >= '2017-01-29' AND date_worked <= '2017-02-04' THEN wh_time_subitem.hours_worked END) as hours_total_old1, 
SUM(CASE WHEN allocation_code_id = '91207' AND date_worked >= '2017-01-29' AND date_worked <= '2017-02-04' THEN wh_time_subitem.hours_worked END) as sick_leave1, 
SUM(CASE WHEN allocation_code_id = '91206' AND date_worked >= '2017-01-29' AND date_worked <= '2017-02-04' THEN wh_time_subitem.hours_worked END) as vacation1, 
SUM(CASE WHEN allocation_code_id = '91209' AND date_worked >= '2017-01-29' AND date_worked <= '2017-02-04' THEN wh_time_subitem.hours_worked END) as personal_leave1, 
SUM(CASE WHEN allocation_code_id = '91208' AND date_worked >= '2017-01-29' AND date_worked <= '2017-02-04' THEN wh_time_subitem.hours_worked END) as holiday1, 
SUM(CASE WHEN allocation_code_id = '30091631' AND date_worked >= '2017-01-29' AND date_worked <= '2017-02-04' THEN wh_time_subitem.hours_worked END) as funeral_leave1, 
ISNULL(MAX(CASE WHEN wh_time_report.period_end_date = '2017-02-11' THEN time_status_id END),0) as timesheet_status2, 
SUM(CASE WHEN date_worked >= '2017-02-05' AND date_worked <= '2017-02-11' THEN ROUND(wh_time_subitem.hours_worked,2) END) as hours_total2, 
SUM(CASE WHEN date_worked >= '2017-02-05' AND date_worked <= '2017-02-11' THEN wh_time_subitem.hours_worked END) as hours_total_old2, 
SUM(CASE WHEN allocation_code_id = '91207' AND date_worked >= '2017-02-05' AND date_worked <= '2017-02-11' THEN wh_time_subitem.hours_worked END) as sick_leave2, 
SUM(CASE WHEN allocation_code_id = '91206' AND date_worked >= '2017-02-05' AND date_worked <= '2017-02-11' THEN wh_time_subitem.hours_worked END) as vacation2, 
SUM(CASE WHEN allocation_code_id = '91209' AND date_worked >= '2017-02-05' AND date_worked <= '2017-02-11' THEN wh_time_subitem.hours_worked END) as personal_leave2, 
SUM(CASE WHEN allocation_code_id = '91208' AND date_worked >= '2017-02-05' AND date_worked <= '2017-02-11' THEN wh_time_subitem.hours_worked END) as holiday2, 
SUM(CASE WHEN allocation_code_id = '30091631' AND date_worked >= '2017-02-05' AND date_worked <= '2017-02-11' THEN wh_time_subitem.hours_worked END) as funeral_leave2 
FROM dbo.wh_resource 
JOIN dbo.wh_department_resource ON wh_resource.resource_id = wh_department_resource.resource_id 
JOIN dbo.wh_department ON wh_department_resource.department_id = wh_department.department_id 
LEFT JOIN wh_time_item ON wh_time_item.user_id = wh_resource.resource_id 
LEFT JOIN wh_time_subitem ON wh_time_subitem.time_item_id = wh_time_item.time_item_id 
LEFT JOIN wh_time_report ON wh_time_report.creator_resource_id = wh_department_resource.resource_id 
WHERE wh_department_resource.is_default_department = 1 
AND wh_resource.is_active = 1 
AND last_name != 'API.User' 
AND wh_department.department_id = '30091606' 
AND department_name NOT IN ('Sales', 'Marketing', 'Operations', '') 
AND (wh_time_report.period_end_date IN ('2017-02-04', '2017-02-11') OR wh_time_report.period_end_date IS NULL) 
GROUP BY wh_resource.resource_id, last_name, first_name, narrative_full_name, hire_date, department_name 
ORDER BY last_name 

Это один запрос возвращает 73 результатов и есть 76 человек, так что, если я сделал запрос, чтобы вытащить людей с

SELECT * FROM dbo.wh_resource 
JOIN wh_department_resource ON wh_resource.resource_id = wh_department_resource.resource_id 
WHERE wh_resource.is_active = 1 
AND department_id = '30091606' 
AND is_default_department ='1' 
ORDER BY last_name, first_name 

Я могу получить все данные, которые мне нужны, в двух запросах в PHP, проверяя, существует ли имя. Но я бы предпочел получить все это в одном запросе!

Редактировать: Используя push SqlZim, у меня есть следующий запрос, который хорошо работает для меня. Это может быть беспорядочно, но он работает быстро (намного быстрее, чем 1000 запросов, которые он заменяет, не шутит). Даты будут предоставлены через PHP, так же как и идентификатор отдела, если это необходимо.

SELECT wh_resource.resource_id, last_name, first_name, narrative_full_name, department_name, 
ISNULL(MAX(CASE WHEN T1.period_end_date = '2017-02-04' THEN T1.time_status_id END),0) as timesheet_status1, 
SUM(CASE WHEN S1.date_worked >= '2017-01-29' AND S1.date_worked <= '2017-02-04' THEN ROUND(S1.hours_worked,2) END) as hours_total1, 
SUM(CASE WHEN S1.date_worked >= '2017-01-29' AND S1.date_worked <= '2017-02-04' THEN S1.hours_worked END) as hours_total_old1, 
SUM(CASE WHEN S1.allocation_code_id = '91207' AND S1.date_worked >= '2017-01-29' AND S1.date_worked <= '2017-02-04' THEN S1.hours_worked END) as sick_leave1, 
SUM(CASE WHEN S1.allocation_code_id = '91206' AND S1.date_worked >= '2017-01-29' AND S1.date_worked <= '2017-02-04' THEN S1.hours_worked END) as vacation1, 
SUM(CASE WHEN S1.allocation_code_id = '91209' AND S1.date_worked >= '2017-01-29' AND S1.date_worked <= '2017-02-04' THEN S1.hours_worked END) as personal_leave1, 
SUM(CASE WHEN S1.allocation_code_id = '91208' AND S1.date_worked >= '2017-01-29' AND S1.date_worked <= '2017-02-04' THEN S1.hours_worked END) as holiday1, 
SUM(CASE WHEN S1.allocation_code_id = '30091631' AND S1.date_worked >= '2017-01-29' AND S1.date_worked <= '2017-02-04' THEN S1.hours_worked END) as funeral_leave1, 
ISNULL(MAX(CASE WHEN T2.period_end_date = '2017-02-11' THEN T2.time_status_id END),0) as timesheet_status2, 
SUM(CASE WHEN S2.date_worked >= '2017-02-05' AND S2.date_worked <= '2017-02-11' THEN ROUND(S2.hours_worked,2) END) as hours_total2, 
SUM(CASE WHEN S2.date_worked >= '2017-02-05' AND S2.date_worked <= '2017-02-11' THEN S2.hours_worked END) as hours_total_old2, 
SUM(CASE WHEN S2.allocation_code_id = '91207' AND S2.date_worked >= '2017-02-05' AND S2.date_worked <= '2017-02-11' THEN S2.hours_worked END) as sick_leave2, 
SUM(CASE WHEN S2.allocation_code_id = '91206' AND S2.date_worked >= '2017-02-05' AND S2.date_worked <= '2017-02-11' THEN S2.hours_worked END) as vacation2, 
SUM(CASE WHEN S2.allocation_code_id = '91209' AND S2.date_worked >= '2017-02-05' AND S2.date_worked <= '2017-02-11' THEN S2.hours_worked END) as personal_leave2, 
SUM(CASE WHEN S2.allocation_code_id = '91208' AND S2.date_worked >= '2017-02-05' AND S2.date_worked <= '2017-02-11' THEN S2.hours_worked END) as holiday2, 
SUM(CASE WHEN S2.allocation_code_id = '30091631' AND S2.date_worked >= '2017-02-05' AND S2.date_worked <= '2017-02-11' THEN S2.hours_worked END) as funeral_leave2 
FROM dbo.wh_resource 
JOIN dbo.wh_department_resource ON wh_resource.resource_id = wh_department_resource.resource_id 
JOIN dbo.wh_department ON wh_department_resource.department_id = wh_department.department_id 
LEFT JOIN wh_time_item ON wh_time_item.user_id = wh_resource.resource_id 
LEFT JOIN wh_time_report T1 ON T1.creator_resource_id = wh_resource.resource_id AND T1.period_end_date = '2017-02-04' 
LEFT JOIN wh_time_subitem S1 ON S1.time_item_id = wh_time_item.time_item_id AND S1.date_worked >= '2017-01-29' AND S1.date_worked < '2017-02-05' 
LEFT JOIN wh_time_report T2 ON T2.creator_resource_id = wh_resource.resource_id AND T2.period_end_date = '2017-02-11' 
LEFT JOIN wh_time_subitem S2 ON S2.time_item_id = wh_time_item.time_item_id AND S2.date_worked >= '2017-02-05' AND S2.date_worked < '2017-02-12' 
WHERE wh_department_resource.is_default_department = 1 
AND wh_resource.is_active = 1 
AND last_name != 'API.User' 
AND wh_department.department_id = '30091606' 
AND department_name NOT IN ('Sales', 'Marketing', 'Operations', '') 
GROUP BY wh_resource.resource_id, last_name, first_name, narrative_full_name, hire_date, department_name 
ORDER BY last_name 
+1

Последние два запроса имеют разные условия, поэтому неудивительно, что вы получаете другой счет. Перед составлением выводов следует сравнить сопоставимые запросы. – trincot

+1

префикс всех столбцов с таблицей или псевдонимом, чтобы было понятно, откуда они. – SqlZim

+0

Внесение псевдонима помогло мне, я постараюсь сделать это больше в будущем! –

ответ

1

Если вы ссылаетесь столбцы в outer join таблицы (слева в данном случае) в вашем where без учета null с, вы будете устранения строк.

Если переместить where условия для ваших условий соединения, вы можете иметь дело с null в твоих select с isnull() и/или coalesce().

Для вашего запроса, который будет выглядеть примерно так:

select 
    wr.resource_id 
    , last_name 
    , first_name 
    , narrative_full_name 
    , department_name 
    , timesheet_status1 = isnull(max(case when wtr.period_end_date = '2017-02-04' then time_status_id end),0) 
    , hours_total1  = sum(case when date_worked >= '2017-01-29' and date_worked <= '2017-02-04' then round(wts.hours_worked,2) end) 
    , hours_total_old1 = sum(case when date_worked >= '2017-01-29' and date_worked <= '2017-02-04' then wts.hours_worked end) 
    , sick_leave1  = sum(case when allocation_code_id = '91207' and date_worked >= '2017-01-29' and date_worked <= '2017-02-04' then wts.hours_worked end) 
    , vacation1   = sum(case when allocation_code_id = '91206' and date_worked >= '2017-01-29' and date_worked <= '2017-02-04' then wts.hours_worked end) 
    , personal_leave1 = sum(case when allocation_code_id = '91209' and date_worked >= '2017-01-29' and date_worked <= '2017-02-04' then wts.hours_worked end) 
    , holiday1   = sum(case when allocation_code_id = '91208' and date_worked >= '2017-01-29' and date_worked <= '2017-02-04' then wts.hours_worked end) 
    , funeral_leave1 = sum(case when allocation_code_id = '30091631' and date_worked >= '2017-01-29' and date_worked <= '2017-02-04' then wts.hours_worked end) 
    , timesheet_status2 = isnull(max(case when wtr.period_end_date = '2017-02-11' then time_status_id end),0) 
    , hours_total2  = sum(case when date_worked >= '2017-02-05' and date_worked <= '2017-02-11' then round(wts.hours_worked,2) end) 
    , hours_total_old2 = sum(case when date_worked >= '2017-02-05' and date_worked <= '2017-02-11' then wts.hours_worked end) 
    , sick_leave2  = sum(case when allocation_code_id = '91207' and date_worked >= '2017-02-05' and date_worked <= '2017-02-11' then wts.hours_worked end) 
    , vacation2   = sum(case when allocation_code_id = '91206' and date_worked >= '2017-02-05' and date_worked <= '2017-02-11' then wts.hours_worked end) 
    , personal_leave2 = sum(case when allocation_code_id = '91209' and date_worked >= '2017-02-05' and date_worked <= '2017-02-11' then wts.hours_worked end) 
    , holiday2   = sum(case when allocation_code_id = '91208' and date_worked >= '2017-02-05' and date_worked <= '2017-02-11' then wts.hours_worked end) 
    , funeral_leave2 = sum(case when allocation_code_id = '30091631' and date_worked >= '2017-02-05' and date_worked <= '2017-02-11' then wts.hours_worked end) 
from dbo.wh_resource as wr 
    inner join dbo.wh_department_resource as wdr 
    on wr.resource_id = wdr.resource_id 
    and wr.is_active = 1 
    and wr.last_name != 'api.user' 
    and wdr.is_default_department = 1 
    inner join dbo.wh_department as wd 
    on wdr.department_id = wd.department_id 
    and wd.department_id = '30091606' 
    and department_name not in ('sales', 'marketing', 'operations', '') 
    left join wh_time_item as wti 
    on wti.user_id = wr.resource_id 
    left join wh_time_subitem as wts 
    on wts.time_item_id = wti.time_item_id 
    left join wh_time_report as wtr 
    on wtr.creator_resource_id = wdr.resource_id 
    and wtr.period_end_date in ('2017-02-04', '2017-02-11') 
group by wr.resource_id, last_name, first_name, narrative_full_name, hire_date, department_name 
order by last_name 
+0

Я никогда не думал присоединяться к таблицам с условием и несколько раз, но как только я попытался и сделал еще какую-то работу, я обнаружил, что соединение таблиц с условиями работало, когда я разделял нагрузку. Я сделал T1/S1 и T2/S2, как 'LEFT JOIN wh_time_report T1 ON T1.creator_resource_id = wh_resource.resource_id И T1.period_end_date = '2017-02-04' LEFT JOIN wh_time_subitem S1 ON S1.time_item_id = wh_time_item.time_item_id AND S1.date_worked> = '2017-01-29' AND S1.date_worked <'2017-02-05'', и когда он запускается, я получаю нужные данные без каких-либо дубликатов или ошибок. Я многому научился сегодня, спасибо! –

+0

@GregEsposito Это имеет смысл. Рад был помочь! – SqlZim

0

Поскольку вы не даете таблицу для period_end_date и time_status_id не уверен
Но попробуйте это

SELECT time_status_id, last_name 
FROM dbo.wh_resource 
LEFT JOIN wh_time_report 
     ON wh_time_report.creator_resource_id = wh_resource.resource_id 
     AND period_end_date >= '2017-01-29' 
WHERE wh_resource.resource_id = '31100670' 

ORDER BY last_name 
0

смущена, но У меня недостаточно времени для работы с полным запросом, который вы предоставили. Вы можете попробовать OUTER APPLY для достижения желаемого результата - получить нуль в случае, если в таблице нет записей, сопоставляемых cirteria.Короткий пример, как это сделать:

SELECT 
    [time_status_id] = a.time_status_id 
    ,[last_name] = a.last_name 
    ,[count] = isnull(b.cnt, 0) 
FROM 
    dbo.wh_resource as a 
outer apply 
    (
     select 
      cnt = count(*) 
     from 
      wh_time_report 
     where 
      creator_resource_id = a.resource_id    
    ) as b  
WHERE a.resource_id = '31100670' 
AND a.period_end_date >= '2017-01-29' 
ORDER BY a.last_name