对于这种情况,做一个自加入的存在吗?
-
21-09-2019 - |
题
我有一个表阿尔法2域组标识,成员:
GroupId | Member;
A1----------A;
A1----------B;
A1----------C;
A2----------A;
A2----------B;
A3----------A;
A3----------D;
A3----------E;
目标: 给出的输入-A,B,C-我们来查询表,以找到,如果一组标识存在于这个确切组成员。所以,这是什么我的计划要做到:
- 查询表为所有GroupIds其计数为3(由于我inpt是A,B,C.I,其3)
- 这将给我A1、A3。现在,查询这个集确切匹配件值..这会给我A1。
我计划写一个存储的过程和将实现的目标。但是,我的问题可以这是实现在一个单一的查询...一个单一的自参加,也许。
澄清:该组(A、B、C)特A1。如果得到输入的(A,B,C,D)查询不应返回A1。
解决方案
答案给予迄今为止假定会员领域是独特的任何给定的组标识.在工作我已经做了这个并不是这种情况。并且,如果集团中有你在寻找什么,外加一些额外的,你需要exlucde,小组。
SELECT
[Alpha].GroupID
FROM
[Alpha]
GROUP BY
[Alpha].GroupID
HAVING
SUM(CASE WHEN [alpha].Member IN ('A','B','C') THEN 1 ELSE 0 END) = 3
AND MIN(CASE WHEN [alpha].Member IN ('A','B','C') THEN 1 ELSE 0 END) = 1
你还可以代替第一个加入到一个表格保持的成员正在寻找...
SELECT
[Alpha].GroupID
FROM
[Alpha]
LEFT JOIN
[Search]
ON [Search].Member
GROUP BY
[Alpha].GroupID
HAVING
SUM(CASE WHEN [alpha].Member = [search].Member THEN 1 ELSE 0 END) = (SELECT COUNT(*) FROM [search])
AND MIN(CASE WHEN [alpha].Member = [search].Member THEN 1 ELSE 0 END) = 1
其他提示
SELECT GroupID
FROM ALPHA
WHERE Member IN ('A', 'B', 'C')
GROUP BY GroupID
HAVING COUNT(*) = 3
这依赖于你的写作出的名单中的成员在条款,并设定的数量(不同)项中的成员名单在有条款。如果你不能产生的SQL正是如此,那么你必须要更加努力地工作。
如指出的,在早期评论,这也依赖于口译,你想要团体在所有三个A、B、C(可能还有其他一些人)成员团。一种方法,不一定是最好的方式,得到'组包含三个人,即A、B、C',是使用:
SELECT GroupID
FROM ALPHA A1
WHERE Member IN ('A', 'B', 'C')
AND 3 = (SELECT COUNT(*) FROM ALPHA A2 WHERE A2.GroupID = A1.GroupID)
GROUP BY GroupID
HAVING COUNT(*) = 3
这明确地检查的总人数在本小组是3和成员都是A、B和C(假定有一个独特的约束,在阿尔法(组标识,会员)使一件不能被列两次为属于同一集团)。
SELECT DISTINCT aa.GroupId
FROM Alpha aa
JOIN Alpha ab ON (aa.GroupId = ab.GroupId)
JOIN Alpha ac ON (aa.GroupId = ac.GroupId)
LEFT OUTER JOIN Alpha ax ON (aa.GroupId = ax.GroupId AND ax.Member NOT IN ('A', 'B', 'C')
WHERE aa.Member = 'A' AND ab.Member = 'B' AND ac.Member = 'C'
AND ax.GroupId IS NULL;
还有涉及解决方案 GROUP BY
但是我找到的 JOIN
解决方案往往具有更好的业绩。我通常的工作MySQL,我理解MS SQL Server是更好的分组查询。所以尝试这两个解决方案,看看什么最为品牌的关系型数据库使用。
试试这个:
declare @YourTable table (GroupID char(2),Member char(1))
insert into @YourTable values ('A1','A')
insert into @YourTable values ('A1','B')
insert into @YourTable values ('A1','C')
insert into @YourTable values ('A2','A')
insert into @YourTable values ('A2','B')
insert into @YourTable values ('A3','A')
insert into @YourTable values ('A3','D')
insert into @YourTable values ('A3','E')
insert into @YourTable values ('A5','A')
insert into @YourTable values ('A5','B')
insert into @YourTable values ('A5','C')
insert into @YourTable values ('A5','D')
SELECT t1.GroupID
FROM @YourTable t1
LEFT OUTER JOIN @YourTable t2 ON t1.GroupID=t2.GroupID AND t2.Member NOT IN ('A', 'B', 'C')
WHERE t1.Member IN ('A', 'B', 'C')
AND t2.GroupID IS NULL
GROUP BY t1.GroupID
HAVING COUNT(*) = 3
输出:
GroupID
-------
A1
(1 row(s) affected)
这里是一个完整的解决方案:
之前你用我的功能,就需要设置"助手"表,你只需要做这一个时间每数据库:
CREATE TABLE Numbers
(Number int NOT NULL,
CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
DECLARE @x int
SET @x=0
WHILE @x<8000
BEGIN
SET @x=@x+1
INSERT INTO Numbers VALUES (@x)
END
使用这种功能分割你的串,不会循环和非常快:
CREATE FUNCTION [dbo].[FN_ListToTable]
(
@SplitOn char(1) --REQUIRED, the character to split the @List string on
,@List varchar(8000) --REQUIRED, the list to split apart
)
RETURNS
@ParsedList table
(
ListValue varchar(500)
)
AS
BEGIN
/**
Takes the given @List string and splits it apart based on the given @SplitOn character.
A table is returned, one row per split item, with a column name "ListValue".
This function workes for fixed or variable lenght items.
Empty and null items will not be included in the results set.
Returns a table, one row per item in the list, with a column name "ListValue"
EXAMPLE:
----------
SELECT * FROM dbo.FN_ListToTable(',','1,12,123,1234,54321,6,A,*,|||,,,,B')
returns:
ListValue
-----------
1
12
123
1234
54321
6
A
*
|||
B
(10 row(s) affected)
**/
----------------
--SINGLE QUERY-- --this will not return empty rows
----------------
INSERT INTO @ParsedList
(ListValue)
SELECT
ListValue
FROM (SELECT
LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
FROM (
SELECT @SplitOn + @List + @SplitOn AS List2
) AS dt
INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
WHERE SUBSTRING(List2, number, 1) = @SplitOn
) dt2
WHERE ListValue IS NOT NULL AND ListValue!=''
RETURN
END --Function FN_ListToTable
你现在可以使用那个这样的功能以查询任何名单:
DECLARE @List varchar(100)
SET @List='A,B,C'
declare @YourTable table (GroupID char(2),Member char(1))
insert into @YourTable values ('A1','A')
insert into @YourTable values ('A1','B')
insert into @YourTable values ('A1','C')
insert into @YourTable values ('A2','A')
insert into @YourTable values ('A2','B')
insert into @YourTable values ('A3','A')
insert into @YourTable values ('A3','D')
insert into @YourTable values ('A3','E')
insert into @YourTable values ('A5','A')
insert into @YourTable values ('A5','B')
insert into @YourTable values ('A5','C')
insert into @YourTable values ('A5','D')
SELECT t1.GroupID
FROM @YourTable t1
LEFT OUTER JOIN @YourTable t2 ON t1.GroupID=t2.GroupID AND t2.Member NOT IN (SELECT ListValue FROM dbo.FN_ListToTable(',',@List))
WHERE t1.Member IN (SELECT ListValue FROM dbo.FN_ListToTable(',',@List))
AND t2.GroupID IS NULL
GROUP BY t1.GroupID
HAVING COUNT(*) = (SELECT COUNT(*) FROM dbo.FN_ListToTable(',',@List))
输出:
GroupID
-------
A1
select*from ALPHA 在件( 选择成员,从阿尔法 小组成员 具有最(*)=3)
试试这个:
SELECT GroupId
FROM ALPHA
GROUP BY GroupId
HAVING SUM(CASE WHEN Member='A' THEN 1.0
WHEN Member='B' THEN 2.0
WHEN Member='C' THEN 4.0
ELSE 7.31415
END) = 7.0
我的建议是解析,delimited string into a temp表,然后再尝试这样的事情。
create table #temp(member varchar(10))
create table #groups
(
groupID varchar(2),
member char(1)
)
--#temp holds the members from your delimited string.
--#groups holds your relationships.
select distinct groupID
from #groups
where
(select count(*) from #groups i, #temp t
where i.member = t.member and i.groupID = #groups.groupID) =
(select count(*) from #temp)