Reputation: 115
First of all thanks for your help.
I have 2 tables, one with orders and the other one with items bought.
Example:
ORDER:
ID
---
1
2
3
4
ORDER_ITEMS:
ID | ORDER_ID | ITEM_ID
---+----------+---------
1 | 1 | 1
2 | 1 | 1
3 | 1 | 2
4 | 1 | 3
5 | 2 | 1
6 | 2 | 2
7 | 2 | 3
8 | 3 | 1
9 | 3 | 1
10 | 3 | 2
11 | 3 | 3
In this case all orders have the same items, but only 2 of them have the same amount of each item.
What I need is that for a given input of ITEM_ID
I can get the ORDER_ID
.
Example:
I have the following query to get the order, item, count:
SELECT
O.ORDER_ID, I.ITEM_ID, count(I.ITEM_ID)
FROM
ORDER AS O
INNER JOIN
ORDER_ITEM AS I ON O.ORDER_ID = I.ORDER_ID
GROUP BY
O.ORDER_ID, I.ITEM_ID
ORDER BY
O.ORDER_ID
With the following output:
ORDER_ID | ITEM_ID | COUNT
---------+----------+------
1 | 1 | 2
1 | 2 | 1
1 | 3 | 1
2 | 1 | 1
2 | 2 | 1
2 | 3 | 1
3 | 1 | 2
3 | 2 | 1
3 | 3 | 1
This is an example input and how i treat it, function just splits the string by ','
DECLARE @ITEM_ID VARCHAR(255)
SET @ITEM_ID = '1,1,2,3'
SELECT DISTINCT(R.sID), COUNT(R.sID) FROM CommaSeparatedToString(@ITEM_ID ) AS R
GROUP BY R.sID
sID | COUNT
1 | 2
2 | 1
3 | 1
With what I already have, how can I achieve the desired output? In this case it would be orders 1 and 3.
Thanks again.
Upvotes: 0
Views: 673
Reputation: 6205
Since you may have duplication items in the same order, you could add a row number as identifier
WITH order AS (SELECT ID, ROW_NUMBER() OVER (ORDER BY ID ASC) as rn from CommaSeparatedToString(@ITEM_ID ))
,
i AS (SELECT *, ROW_NUMBER() OVER (PARTITION BY [ORDER_ID] ORDER BY [ITEM_ID] ASC) as rn from ORDER_ITEMS)
SELECT i.ORDER_ID
FROM i
LEFT JOIN order o
ON o.ID = i.ITEM_ID AND i.rn = o.rn
GROUP BY i.ORDER_ID
HAVING
COUNT(i.ID) = COUNT(o.rn) -- ORDER_ITEMS match every order in the order list
AND
COUNT(i.ID) = (SELECT COUNT(*) from order) -- ORDER_ITEMS have exact number of the order list
Upvotes: 1
Reputation: 2507
Starting from where you have got - my #counts table is your count by order and item, my #findme is the output of your last query representing what you are searching for.
create table #counts
(
order_id int,
item_id int,
cnt int
);
insert into #counts values
(1, 1 ,2),
(1, 2 ,1),
(1, 3 ,1),
(2, 1 ,1),
(2, 2 ,1),
(2, 3 ,1),
(3, 1 ,2),
(3, 2 ,1),
(3, 3 ,1);
create table #findme
(
item_id int,
cnt int
);
insert into #findme values
(1,2),
(2,1),
(3,1);
-- get count of different items per order
select order_id,
count(*) as cnt
into #itemcnt
from #counts
group by order_id
-- now join our search query and see how many rows match on both item and count
select order_id, count(*) cnt
into #found
from #findme
inner join #counts
on #findme.item_id = #counts.item_id
and #findme.cnt = #counts.cnt
group by order_id
-- now join this to see where number of matches = number of different items
select distinct #found.order_id
from #found
inner join #itemcnt on #found.cnt = #itemcnt.cnt
Upvotes: 0
Reputation: 1269633
If you want to provide input as "1,1,2,3", then the simplest solution is to aggregation the values:
select o.*
from (select o.*,
stuff( (select ',' + cast(oi.item_id as varchar(255))
from order_items oi
where oi.order_id = o.id
order by oi.item_id
for xml path ('')
), 1, 1, '') as items
from orders o
) o
where items in ('1,1,2,3');
Upvotes: 3