我有一张具有以下结构的表格。
Table Name: CustomerStocks
Structure
Name Varchar(25)
StockSymbol Varchar(4)
以下是表格内容的样本
名称StockSymbol
Sam AAPL
Sam AMZN
Sam GOOG
Judy AAPL
Judy AMZN
Jen AMZN
Brian GOOG
Brian MSFT
目标是给出客户名称,如何找到具有类似投资组合的其他客户的列表。换句话说,原始客户的所有股票必须存在。
因此,如果我正在寻找拥有类似Jen的投资组合的客户,那么结果将是Judy和Sam。
如果我正在寻找拥有类似Judy组合的客户,那么结果将是Sam。
但是,如果我在寻找拥有Brian的投资组合的客户,它可以返回任何行或只返回Brian。
这可能吗?如果是这样,我如何编写一个SQL查询来实现这个目标?
对此我们非常感激。
答案 0 :(得分:2)
(稍后稍作调整......)
我没有对此进行过测试,但有些像......
DECLARE @name VARCHAR(24) = 'Judy';
WITH cte_stocks AS (
SELECT StockSymbol
FROM CustomerStocks
WHERE Name = @name
)
SELECT Name
FROM CustomerStocks cs
LEFT JOIN cte_stocks a ON cs.StockSymbol = a.StockSymbol
GROUP BY cs.Name
HAVING COUNT(DISTINCT a.StockSymbol) = (SELECT COUNT(1) FROM cte_stocks)
......可能会这样做
答案 1 :(得分:0)
这应该有效:
declare @Name varchar(25) = 'Judy'
select * from CustomerStocks cs
where cs.StockSymbol in
(select x.StockSymbol
from CustomerStocks x
where x.Name = @Name)
或排除朱迪:
declare @Name varchar(25) = 'Judy'
select * from CustomerStocks cs
where cs.StockSymbol in
(select x.StockSymbol
from CustomerStocks x
where x.Name = @Name
and x.Name <> cs.Name)
答案 2 :(得分:0)
好的,那怎么样:
declare @Name Varchar(25) = 'Judy'
declare @table (StockSymbol varchar(4))
--Get StockSymbols to search for
insert into @table
select cs.StockSymbol
from CustomerStocks cs
where cs.Name = @Name
group by cs.StockSymbol
--Match against the people
select cs.Name from CustomerStocks cs
where (select count(*)
from CustomerStocks x
inner join @table t on x.StockSymbol = t.StockSymbol
where x.Name = cs.Name
group by x.StockSymbol) = (select count(*) from @table t)
group by cs.Name
答案 3 :(得分:0)
这样的东西可能有效,与引擎无关:
SELECT target.Name, 'similar_to', others.Name
FROM (
SELECT Name, COUNT(*) numStocks
FROM CustomerStocks
GROUP BY Name
) target
INNER JOIN (
SELECT cs1.Name match, cs2.Name otherName, count(*) commonStocks
FROM CustomerStocks cs1
INNER JOIN CustomerStocks cs2
ON cs1.StockSymbol = cs2.StockSymbol
AND cs1.Name <> cs2.Name
GROUP BY cs1.Name, cs2.Name
) others ON target.Name = others.match
AND others.commonStocks >= numStocks.numStocks
答案 4 :(得分:0)
NOT EXISTS()和EXCEPT运营商的选项
DECLARE @Name Varchar(25) = 'Judy'
SELECT *
FROM dbo.CustomerStocks s
WHERE NOT EXISTS (
SELECT s3.StockSymbol
FROM dbo.CustomerStocks s3
WHERE s3.Name = @Name
EXCEPT
SELECT s2.StockSymbol
FROM dbo.CustomerStocks s2
WHERE s2.Name = s.Name
) AND s.Name != @Name
为了提高性能,请使用此索引
CREATE INDEX ix_StockSymbol_CustomerStocks ON CustomerStocks(StockSymbol) INCLUDE(Name)
SQLFiddle上的演示