2013-09-16 6 views
0

Я изо всех сил пытаюсь размахивать этим слоем.sql 2000 select id, где выполняются условия нескольких строк.

У меня есть функция, которая возвращает список элементов, связанных с спецификацией спецификаций.

Результат SQL выберите

SELECT 
    BOM, 
    ITEMID, 
    QTY 
FROM boms 
WHERE 
    bom='A' 

является

BOM  | ITEMID  | QTY 
A  | ITEMB  | 1 
A  | ITEMC  | 2 

Теперь с помощью этого набора результатов я ищу, чтобы запросить мой salestable найти продажи, где ITEMB и ITEMC были проданы в достаточном количестве.

Формат salestable выглядит следующим образом

SELECT 
    salesid, 
    itemid, 
    sum(qtyordered) 'ordered' 
FROM salesline 
WHERE 
    itemid='ITEMB' 
    or itemid='ITEMC' 
GROUP BY salesid, itemid 

Это дало бы мне что-то вроде

salesid | itemid | ordered 
SO-10000 | ITEMB | 1 
SO-10001 | ITEMB | 1 
SO-10001 | ITEMC | 1 
SO-10002 | ITEMB | 1 
SO-10002 | ITEMC | 2 

идеале я хотел бы вернуться только SO-10002, поскольку это единственная продажа, где все необходимые единицы были проданы.

Любые предложения будут оценены. В идеале один запрос был бы идеальным, но я не уверен, что это возможно. Производительность не обязательна, так как это будет выполняться раз в неделю ранним утром.

EDIT

с всегда превосходной помощи, код завершен. Я завернул все это в UDF, который просто возвращает продажи для указанной спецификации в течение определенного периода времени.

Функция

CREATE FUNCTION [dbo].[BOMSALES] (@bom varchar(20),@startdate datetime, @enddate datetime) 
RETURNS TABLE 
AS 
RETURN(
select count(q.SALESID) SOLD FROM (SELECT s.SALESID 
FROM 
(
    SELECT s.SALESID, ITEMID, SUM(qtyordered) AS SOLD 
    FROM salesline s inner join SALESTABLE st on st.salesid=s.SALESID 
    where st.createddate>[email protected] and st.CREATEDDATE<[email protected] and st.salestype=3 
    GROUP BY s.SALESID, ITEMID 
) AS s 
JOIN dbo.BOM1 AS b ON b.ITEMID = s.ITEMID AND b.QTY <= s.SOLD 
where [email protected] 
GROUP BY s.SALESID 
HAVING COUNT(*) = (SELECT COUNT(*) FROM dbo.BOM1 WHERE BOM = @bom)) q 
) 
+1

Я не понимаю, почему вам нужен первый запрос. Возможно, вы могли бы объяснить проблему немного более четко? Как вы получаете сумму «продано в достаточном количестве»? Кроме того, работает ли ваш второй запрос? Я думал, что у вас есть сводная функция, такая как работа СУММ, у вас должен был быть предложение GROUP BY? – Ryan

+0

Привет @Ryan - да, вы правы в отношении второго запроса - это была очень упрощенная версия фактического выбора. Я отредактировал его, чтобы включить группу. Что касается того, почему первое - мне нужно найти, какие компоненты BOM A состоит из первого и сколько из каждого элемента требуется. – l0ckm4

+0

Будет ли это работать только для одного «bom»? – dnoeth

ответ

1

Это должно вернуть все продажи с точным соответствием, то же Itemid и такое же количество:

SELECT s.salesid 
FROM 
(
    SELECT salesid, itemid, SUM(qtyordered) AS ordered 
    FROM salesline AS s 
    GROUP BY salesid, itemid 
) AS s 
JOIN 
    boms AS b 
ON b.itemid = s.itemid 
AND b.QTY = s.ordered 
WHERE b.BOM='A' 
GROUP BY s.salesid 
HAVING COUNT(*) = (SELECT COUNT(*) FROM boms WHERE BOM='A'); 

Если вы хотите вернуть продажу, где количество превышает boms.qty youhave, чтобы изменить соответствующим образом присоединиться :

JOIN 
    boms AS b 
ON b.itemid = s.itemid 
AND b.QTY <= s.ordered 

Непроверено ...

+0

Спасибо за помощь - с незначительными модами это делает то, что мне нужно :-) – l0ckm4

0

Вы можете сделать это агрегирование и пункт having:

select salesid 
from salesline sl 
group by salesid 
having sum(case when itemid = 'ITEMB' then 1 else 0 end) > 0 and 
     sum(case when itemid = 'ITEMA' then 1 else 0 end) > 0; 

Каждое условие в предложении having подсчитывает количество строк с каждым элементом.

+0

Спасибо за ваш ответ, но код @dnoeth выше работает динамически, без необходимости знать компоненты рассматриваемой спецификации. – l0ckm4

+0

@ l0ckm4. , , Ваш отредактированный вопрос имеет большое значение. –

0

Я думаю, что это может получить результаты вам нужно. Вы должны будете заменить @BOM с бом:

SELECT 
    DISTINCT salesid 
FROM 
    salesline sl 
INNER JOIN boms b ON 
    b.bom = @BOM 
    AND b.itemid = sl.itemid 
GROUP BY salesid, itemid 
HAVING SUM(qtyordered) >= b.qty 

Из того, что я понимаю, первый запрос используется для получения пороговых значений для возвращения квалификационных продаж? Основываясь на ваших примерах строк данных, я предположил, что в таблице торговых линий будет только одна строка для salesid + itemid (в основном действующая как первичный ключ с двойным полем)? Если это так, я не думаю, что есть необходимость делать СУММУ, как у вас во втором примере запроса. Дайте мне знать, если я ошибаюсь в любых моих предположениях, и я отрегулирую свой ответ.

+0

Привет @Ryan - Мне действительно нужна сумма, так как наша система позволяет qtyorderd быть 1 !!!! Поэтому нам нужно иметь отдельные линии для нескольких величин! – l0ckm4

+0

Хорошо, отредактировал запрос. Дайте мне знать, если вы получите желаемый результат. – Ryan

+0

Это не работает для моих данных - оно возвращает больше продаж, чем ожидалось. Мне кажется, что код @dnoeth ниже работает. Спасибо за ваше время, хотя я это ценю. – l0ckm4

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