我有一个名为Transactions的表,通过items_transactions表与项目有多对多关系。
我想做这样的事情:
SELECT "transactions".*
FROM "transactions"
INNER JOIN "items_transactions"
ON "items_transactions".transaction_id = "transactions".id
INNER JOIN "items"
ON "items".id = "items_transactions".item_id
WHERE (items.id IN (<list of items>))
但是这给了我所有与列表中的一个或多个项目相关联的交易,我只希望它给我与所有这些项目相关联的交易。
任何帮助都将不胜感激。
答案 0 :(得分:9)
您必须展开列表中所有项目的查询:
SELECT "transactions".*
FROM "transactions"
WHERE EXISTS (SELECT 1 FROM "items_transactions"
INNER JOIN "items" ON "items".id = "items_transactions".item_id
WHERE "items_transactions".transaction_id = "transactions".id
AND "items".id = <first item in list>)
AND EXISTS (SELECT 1 FROM "items_transactions"
INNER JOIN "items" ON "items".id = "items_transactions".item_id
WHERE "items_transactions".transaction_id = "transactions".id
AND "items".id = <second item in list>)
...
您也可以使用IN
和COUNT DISTINCT
按摩它,我不确定哪个更快。像(完全未经测试)的东西:
SELECT "transactions".*
FROM "transactions"
INNER JOIN (SELECT "items_transactions".transaction_id
FROM "items_transactions"
INNER JOIN "items" ON "items".id = "items_transactions".item_id
WHERE "items".id IN (<list of items>)
GROUP BY "items_transactions".transaction_id
HAVING COUNT(DISTINCT "items".id) = <count of items in list>) matches ON transactions.transaction_id = matches.transaction_id
答案 1 :(得分:1)
我认为这可以满足您的需求。
我会把你需要的项目列表放到一个表格中(临时一个会好的)并加入到那个。然后计算不同项目的数量,并将计数与项目交易计数相匹配。
我提供了样本DDL&amp;我使用的数据。
Create table #trans
(
transId int identity(1,1),
trans varchar(10)
)
Create Table #itemTrans
(
transId int,
itemId int
)
Create table #items
(
itemId int identity(1,1),
item varchar(10)
)
Create table #itemsToSelect
(
itemId int
)
Insert Into #trans
Values ('Trans 1')
Insert Into #trans
Values ('Trans 2')
Insert Into #trans
Values ('Trans 3')
Insert Into #Items
Values ('Item 1')
Insert Into #Items
Values ('Item 2')
Insert Into #Items
Values ('Item 3')
Insert Into #Items
Values ('Item 4')
Insert Into #itemTrans
Values (1, 1)
Insert Into #itemTrans
Values (1, 2)
Insert Into #itemTrans
Values (1, 3)
Insert Into #itemTrans
Values (2, 1)
Insert Into #itemTrans
Values (2, 3)
Insert Into #itemTrans
Values (3, 4)
Insert Into #itemsToSelect
Values (1)
Insert Into #itemsToSelect
Values (2)
Insert Into #itemsToSelect
Values (3)
Select t.transId
From #items i
Join #itemTrans it on i.itemId = it.itemId
Join #trans t on it.transId = t.transId
Join #itemsToSelect its on it.ItemId = its.ItemId
Where it.TransId is not null
Group by t.transId
Having count(distinct(it.itemId)) = (Select count(distinct(itemId)) from #itemsToSelect)
答案 2 :(得分:1)
SELECT transactions.*
WHERE (SELECT count(*)
FROM items_transactions
WHERE items_transactions.transaction_id = transactions.transaction_id
AND items_transactions.item_id IN (<list of items>)
) = <number of items>
虽然这可能会对事务进行扫描,但是为每个事务嵌套相关子查询...不是特别有效,所以可能:
SELECT transactions.*
WHERE EXISTS (SELECT 1 FROM items_transactions
WHERE items_transactions.transaction_id = transactions.transaction_id
AND items_transactions.item_id IN (<list of items>)
)
AND
(SELECT count(*)
FROM items_transactions
WHERE items_transactions.transaction_id = transactions.transaction_id
AND items_transactions.item_id IN (<list of items>)
) = <number of items>
或类似的东西,说服数据库首先找到与至少一个项目相关的交易,然后检查每个交易是否与以后的所有项目相关联。
正如有人所说,你也可以简单地为每个项目生成连接子句,如果项目数量不大,这可能会更好。
答案 3 :(得分:0)
查询的最后一位看起来不对:
WHERE (items.id IN (<list of items>))
'in'语句就像一个大的OR语句而不是AND语句,因此它被优化器扩展为:
WHERE (items.id = 123 OR items.id = 456 OR items.id = 789)
修改强>
我估计您需要在项目表上执行correlated subquery。
答案 4 :(得分:0)
我没有执行此操作,但这应该可以获得您想要的结果:
SELECT t.* FROM items i
INNER JOIN items_transactions it ON i.id = it.item_id
INNER JOIN transactions t ON it.transaction_id = t.id
WHERE i.id IN (1,2,3)