У меня есть то, что кажется поврежденным индексом?
Вот что происходит. У меня есть две табличные функции, первая из которых - набор наблюдений, а вторая - набор осведомленных дат. Эти два набора имеют отношение 1 (регистр) к 0 или 1 (дата осведомленности). Обычно я запрашиваю их как;
SELECT c.CaseID, a.AwareDate
FROM Cases(@date) AS c
LEFT JOIN AwareDates(@date) AS a ON c.CaseID = a.CaseID;
Беда в том, что не все строки из AwareDates, которые соответствуют, кажутся JOIN'd. Если я добавлю подсказку присоединения, они тогда сделают. говорят,
SELECT c.CaseID, a.AwareDate
FROM Cases(@date) AS c
LEFT MERGE JOIN AwareDates(@date) AS a ON c.CaseID = a.CaseID;
Что я заметил в плане запросов, так это то, что добавление подсказки о соединении добавляет данные AwareDate своего рода перед соединением, которых в противном случае нет. Кроме того, планировщик запросов переворачивает соединение в ПРАВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ, когда нет подсказки, и, конечно, сохраняет левое соединение там, где есть подсказка.
Я сделал следующее без ошибок;
DBCC UPDATEUSAGE (0) WITH INFO_MESSAGES, COUNT_ROWS;
EXECUTE sp_updatestats 'resample';
DBCC CHECKDB (0) WITH ALL_ERRORMSGS, EXTENDED_LOGICAL_CHECKS;
Я в тупике ... есть идеи?
Вот определения UDF
ALTER FUNCTION dbo.Cases( @day date ) RETURNS TABLE
WITH SCHEMABINDING
AS RETURN (
SELECT
CaseID -- other 42 columns ommitted
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY CaseID ORDER BY UpdateDate DESC, UpdateNumber DESC) AS RecordAge,
CaseID,
Action
FROM
dbo.CaseAudit
WHERE
convert(date,UpdateDate) <= @day
) AS History
WHERE
RecordAge = 1 -- only the most current record version
AND isnull(Action,'') != N'DEL' -- only include cases that have not been deleted
)
ALTER FUNCTION dbo.AwareDates( @day date ) RETURNS TABLE
WITH SCHEMABINDING
AS RETURN (
WITH
History AS (
SELECT row_number() OVER (PARTITION BY CaseID, ContactID ORDER BY UpdateDate DESC, UpdateNumber DESC) AS RecordAge,
CaseID, InfoReceived, ReceiveDate, ResetClock, Action
FROM dbo.ContactLogAudit WITH (NOLOCK)
WHERE convert(date,UpdateDate) <= @day
),
Notes AS (
SELECT
CaseID,
convert(date,ReceiveDate,112) AS ReceiveDate,
ResetClock
FROM History
WHERE RecordAge = 1 -- only the most current record version
AND isnull(Action,'') != N'DEL' -- only include notes that have not been deleted
AND InfoReceived = N'Y' -- only include notes that have Info Rec'd checked
AND len(ReceiveDate) = 8 AND isnumeric(ReceiveDate) = 1 AND isdate(ReceiveDate) = 1 -- only include those with a valid aware date
),
Initials AS (
SELECT CaseID, min(ReceiveDate) AS ReceiveDate
FROM Notes
GROUP BY CaseID
),
Resets AS (
SELECT CaseID, max(ReceiveDate) AS ReceiveDate
FROM Notes
WHERE ResetClock = N'Y'
GROUP BY CaseID
)
SELECT
i.CaseID AS CaseID,
i.ReceiveDate AS InitialAwareDate, -- the oldest valid aware date value (must have AE Info Reveived checked and a received date)
coalesce(r.ReceiveDate,i.ReceiveDate) AS AwareDate -- either the newest valid aware date value with the Reset Clock checked, otherwise the initial aware date value
FROM Initials AS i
LEFT JOIN Resets AS r
ON i.CaseID = r.CaseID
);
Я также обнаружил, что если я опущу табличную подсказку WITH (NOLOCK), я получу правильные результаты. Также, если добавить подсказку о соединении в UTF AwareDates или даже добавить COLLATE Latin1_General_BIN в отношении LEFT JOIN между инициалами и сбросами.
Количество строк в плане запроса - без подсказки соединения (не работает)
- Дела {Фактические: 25 891, Эстимейт: 19 071,9}
- AwareDates {Фактический: 24 693, Расчетный: 1 463,09}
- Инициалы {Фактические: 24 693, Расчетные: 1 463,09}
- Отдыхает {Фактический: 985, Расчетный: 33.2671}
- AwareDates соответствует 8,108 строк Cases в наборе результатов объединения
Количество строк в плане запроса - с подсказкой соединения (работает)
- Дела {Фактические: 25 891, Эстимейт: 19 071,9}
- AwareDates {Фактический: 24 673, Расчетный: 1 837,67}
- Инициалы {Фактические: 24 673, Расчетные: 1 837,67}
- Отдыхает {Фактический: 982, Расчетный: 42.6238}
- AwareDates соответствует 24 673 строкам Cases в наборе результатов объединения
Я еще больше сократил суть вопроса. Я могу;
SELECT * FROM AwareDate(@date);
и
SELECT * FROM AwareDate(@date) ORDER BY CaseID;
С разным количеством строк.