Одним из решений может быть создание декартового произведения всех ожидаемых строк с использованием декартового произведения между (фиксированным) списком значений, а затем LEFT JOIN
с помощью current_view
.
Следующий запрос гарантирует, что вы получите запись для каждого заданного кортежа s_date/part_no/issue_group/s_level
. Если в current_view
не найдено ни одной записи, запрос отобразит количество 0
.
SELECT
sd.s_date,
pn.part_no,
ig.issue_group,
sl.s_level,
COALESCE(cv.qty_filled, 0) qty_filled
FROM
(SELECT '201802' AS s_date UNION SELECT '201803') AS sd
CROSS JOIN (SELECT 'xxxxx' AS part_no) AS pn
CROSS JOIN (SELECT '1' AS issue_group UNION SELECT '2') AS ig
CROSS JOIN (SELECT '80' AS s_level UNION SELECT '100' UNION SELECT 'Late') AS sl
LEFT JOIN current_view cv
ON cv.s_date = sd.s_date
AND cv.part_no = pn.part_no
AND cv.issue_group = ig.issue_group
AND cv.s_level = ig.s_level
ORDER BY
sd.s_date,
pn.part_no,
ig.issue_group,
DECODE(sl.s_level, '80', 1, '100', 2, 'Late', 3)
Примечание: вы не пометили свою СУБД. Это должно работать на большинстве из них, за исключением Oracle, где вам нужно добавить FROM DUAL
к каждому выбору в запросах, которые перечисляют допустимые значения, например:
(SELECT '201802' AS s_date FROM DUAL UNION SELECT '201803' FROM DUAL) AS sd
Как был указан ниже, передав a COM
указатель на интерфейс между потоками в не безопасный.
Принятие Вас знает то, что Вы делаете:
hThread = CreateThread(
NULL,
0,
SecondaryThread,
(LPVOID) pis8
0,
&dwGenericThreadID);
DWORD WINAPI SecondaryThread(LPVOID iValue)
{
((IS8Simulation*) iValue)->Open();
}
Ориентированная на многопотоковое исполнение версия:
void MainThread()
{
IStream* psis8;
HRESULT res = CoMarshalInterThreadInterfaceInStream (IID_IS8SIMULATION, pis8, &psis8);
if (FAILED(res))
return;
hThread = CreateThread(
NULL,
0,
SecondaryThread,
(LPVOID) psis8
0,
&dwGenericThreadID
);
}
DWORD WINAPI SecondaryThread(LPVOID iValue)
{
IS8Simulation* pis8;
HRESULT res = CoGetInterfaceAndReleaseStream((IStream*) iValue, IID_IS8SIMULATION, &pis8);
if (FAILED(res))
return (DWORD) res;
pis8->Open();
}
В основном необходимо сделать следующее:
CoMashalInterThreadInterfaceInStream
==> Вы получаете интерфейс IStream. CoGetInterfaceAndReleaseStream
получить интерфейс (или прокси к нему, при необходимости). Не выпускайте интерфейс IStream, если создание сбоев потока, и не выходит из потока, пока yu не звонили CoGetInterfaceAndReleaseStream
.
Время выполнения COM создаст прокси для Вас автоматически. Прокси гарантирует, что, например, поточный квартирой COM-компонент назван на потоке, который создал его. Однако это также требует что:
Если интерфейс в Вашем вопросе является COM-интерфейсом, подход, данный Quassnoi, не мог бы быть достаточным. Необходимо обратить внимание на модель потоков используемого COM-объекта. Если вторичный поток присоединится к отдельной квартире COM от той, что Ваш COM-объект был создан в, и если тот объект не будет гибким квартирой, то необходимо будет упорядочить тот указатель на интерфейс так, чтобы вторичный поток получил прокси и не прямой указатель на объект.
COM-объект обычно делается гибким квартирой при помощи специальной реализации IMarshal. Самый простой подход должен агрегировать Marshaler Со свободными потоками.
Некоторые полезные ссылки...
Обновление: о Marshaler со свободными потоками...
Это ясно из комментариев к этой теме, что некоторые люди рекомендовали бы никогда не касаться FTM. В то время как "Эффективный COM" является превосходной книгой, я думаю, что некоторые ее рекомендации открыты для интерпретации. Объект 33 говорит, "Остерегаются FTM"; это не говорит, "Никогда не используют FTM". Очень мудро это советует осторожности особенно, когда Ваш гибкий квартирой объект содержит ссылки на другие объекты, потому что они не могли бы быть гибкими квартирой. Таким образом, действительно совет: думайте тщательно при создании гибких квартирой объектов, используют ли они FTM для достижения их гибкости. Если бы Вы уверены, что можно создать гибкий квартирой объект, я не вижу оснований, почему Вы не использовали бы FTM для достижения этого.