我有一个非常狭窄的表:user_id,ancestry。
user_id列是不言自明的。
祖先栏包含用户祖先欢呼的国家/地区。
用户可以在桌面上拥有多行,因为用户可以拥有来自多个国家/地区的祖先。
我的问题是:如何选择其祖先来自多个指定国家/地区的用户?
例如,向我展示所有拥有来自英格兰,法国和德国的祖先的用户,并为每个符合该标准的用户返回1行。
那是什么SQL?
user_id ancestry
--------- ----------
1 England
1 Ireland
2 France
3 Germany
3 Poland
4 England
4 France
4 Germany
5 France
5 Germany
在上述数据的情况下,我预计结果为“4”,因为user_id 4有来自英格兰,法国和德国的祖先。
提前致谢。
P.S。澄清:是的,user_id / ancestry列创建一个唯一的对,因此不会为给定用户重复一个国家/地区。
P.P.S。我正在寻找来自所有3个国家的用户 - 英格兰,法国和德国(以及这些国家是任意的)。
P.P.P.S。我不是在寻找特定于某个RDBMS的答案。我希望“一般地”回答这个问题。
我满足于为每个查询重新生成where子句,前提是可以通过编程方式生成where子句(例如,我可以构建一个函数来构建WHERE / FROM - WHERE子句)。
答案 0 :(得分:21)
试试这个:
Select user_id
from yourtable
where ancestry in ('England', 'France', 'Germany')
group by user_id
having count(user_id) = 3
最后一行表示用户的祖先拥有所有3个国家。
答案 1 :(得分:5)
3个国家/地区
之一的用户SELECT DISTINCT user_id
FROM table
WHERE ancestry IN('England','France','Germany')
拥有所有3个国家/地区
的用户SELECT DISTINCT A.userID
FROM table A
INNER JOIN table B on A.user_id = B.user_id
INNER JOIN table C on A.user_id = C.user_id
WHERE A.ancestry = 'England'
AND B.ancestry = 'Germany'
AND C.ancestry = 'France'
答案 2 :(得分:5)
SELECT DISTINCT (user_id)
FROM [user]
WHERE user.user_id In (select user_id from user where ancestry = 'England')
And user.user_id In (select user_id from user where ancestry = 'France')
And user.user_id In (select user_id from user where ancestry = 'Germany');`
答案 3 :(得分:0)
吸引多个国家的人:
SELECT u1.user_id
FROM users u1
JOIN users u2
on u1.user_id = u2.user_id
AND u1.ancestry <> u2.ancestry
从2个特定国家/地区获取人员:
SELECT u1.user_id
FROM users u1
JOIN users u2
on u1.user_id = u2.user_id
WHERE u1.ancestry = 'Germany'
AND u2.ancestry = 'France'
3个国家......加入三次。只获得一次结果,不同。
这将获得具有3行(具有...计数)的用户,然后指定允许哪些行。请注意,如果(user_id, ancestry)
上没有UNIQUE KEY,则出现3次'id,england'的用户也会匹配...所以这取决于您的表结构和/或数据。
SELECT user_id
FROM users u1
WHERE ancestry = 'Germany'
OR ancestry = 'France'
OR ancestry = 'England'
GROUP BY user_id
HAVING count(DISTINCT ancestry) = 3
答案 4 :(得分:0)
如果您希望获得满足所有条件的所有user_id,那么其中一种方法是:
SELECT DISTINCT user_id FROM table WHERE ancestry IN ('England', '...', '...') GROUP BY user_id HAVING count(*) = <number of conditions that has to be satisfied>
等。如果您需要获取满足至少一个条件的所有user_id,那么您可以执行
SELECT DISTINCT user_id from table where ancestry IN ('England', 'France', ... , '...')
我不知道是否有类似IN的东西但是用AND而不是OR
连接条件答案 5 :(得分:0)
select distinct usr_id from users where user_id in (
select user_id from (
Select user_id, Count(User_Id) As Cc
From users
GROUP BY user_id
) Where Cc =3
)
and ancestry in ('England', 'France', 'Germany')
;
编辑:我更喜欢@HuckIt的回答。
答案 6 :(得分:0)
这个问题已有几年了,但我是通过重复发表的。我也想提出一个更通用的解决方案。如果您知道您始终拥有固定数量的祖先,则可以使用一些自我联接,如答案中已建议的那样。如果你想要一个通用的方法继续阅读。
这里你需要的是关系代数中的商数。商数或多或少是笛卡尔积(或SQL中的交叉连接)的逆转。
假设您的祖先集A
是(我在这里使用表格符号,我认为这对理解更好)
ancestry
-----------
'England'
'France'
'Germany'
您的用户集U
是
user_id
--------
1
2
3
笛卡儿积C=AxU
则为:
user_id | ancestry
---------+-----------
1 | 'England'
1 | 'France'
1 | 'Germany'
2 | 'England'
2 | 'France'
2 | 'Germany'
3 | 'England'
3 | 'France'
3 | 'Germany'
如果你计算设定商U=C/A
,那么你得到
user_id
--------
1
2
3
如果您重做笛卡尔积UXA
,您将再次获得C
。但请注意,对于一组T
,(T/A)xA
不一定会重现T
。例如,如果T
是
user_id | ancestry
---------+-----------
1 | 'England'
1 | 'France'
1 | 'Germany'
2 | 'England'
2 | 'France'
然后(T/A)
user_id
--------
1
然后 (T/A)xA
user_id | ancestry
---------+------------
1 | 'England'
1 | 'France'
1 | 'Germany'
请注意,商家和笛卡尔产品操作已消除user_id=2
的记录。
您的问题是:哪个user_id有祖先所有国家/地区的祖先?换句话说,您需要U=T/A
,其中T
是您的原始集(或您的表)。
要在SQL中实现商,您必须执行4个步骤:
让我们一步一步来做。我将使用TSQL语法(Microsoft SQL服务器),但它应该很容易适应其他DBMS。作为表(user_id, ancestry)
的名称,我选择ancestor
CREATE TABLE ancestry_set (ancestry nvarchar(25))
INSERT INTO ancestry_set (ancestry) VALUES ('England')
INSERT INTO ancestry_set (ancestry) VALUES ('France')
INSERT INTO ancestry_set (ancestry) VALUES ('Germany')
CREATE TABLE ancestor ([user_id] int, ancestry nvarchar(25))
INSERT INTO ancestor ([user_id],ancestry) VALUES (1,'England')
INSERT INTO ancestor ([user_id],ancestry) VALUES(1,'Ireland')
INSERT INTO ancestor ([user_id],ancestry) VALUES(2,'France')
INSERT INTO ancestor ([user_id],ancestry) VALUES(3,'Germany')
INSERT INTO ancestor ([user_id],ancestry) VALUES(3,'Poland')
INSERT INTO ancestor ([user_id],ancestry) VALUES(4,'England')
INSERT INTO ancestor ([user_id],ancestry) VALUES(4,'France')
INSERT INTO ancestor ([user_id],ancestry) VALUES(4,'Germany')
INSERT INTO ancestor ([user_id],ancestry) VALUES(5,'France')
INSERT INTO ancestor ([user_id],ancestry) VALUES(5,'Germany')
1)创建祖先集的笛卡尔积和所有user_ids的集合。
SELECT a.[user_id],s.ancestry
FROM ancestor a, ancestry_set s
GROUP BY a.[user_id],s.ancestry
2)查找笛卡尔积中与原始集合中没有合作伙伴的所有记录(左连接)和
3)从2)
的结果集中提取user_idsSELECT DISTINCT cp.[user_id]
FROM (SELECT a.[user_id],s.ancestry
FROM ancestor a, ancestry_set s
GROUP BY a.[user_id],s.ancestry) cp
LEFT JOIN ancestor a ON cp.[user_id]=a.[user_id] AND cp.ancestry=a.ancestry
WHERE a.[user_id] is null
4)返回原始集合中未包含在3)
结果集中的所有user_idSELECT DISTINCT [user_id]
FROM ancestor
WHERE [user_id] NOT IN (
SELECT DISTINCT cp.[user_id]
FROM (SELECT a.[user_id],s.ancestry
FROM ancestor a, ancestry_set s
GROUP BY a.[user_id],s.ancestry) cp
LEFT JOIN ancestor a ON cp.[user_id]=a.[user_id] AND cp.ancestry=a.ancestry
WHERE a.[user_id] is null
)
答案 7 :(得分:0)
像上面的答案一样,但是我有一个重复的记录,所以我必须创建一个与众不同的子查询
public class MainViewModel
{
public IEnumerable<Header> Headers { get; } = new Header[]
{ new Header { Value = "1" }, new Header { Value = "2" } };
public string[,] Items { get; } = new string[2, 2] { { "1", "2" }, { "3", "4" } };
}
public class Header
{
public string Value { get; set; }
public override string ToString()
{
return Value;
}
}
这是我使用的,因为我有多个记录(下载日志),并且它检查是否已下载所有必需的文件
答案 8 :(得分:0)
我遇到了类似您的问题,除了我想要特定的“祖先”子集。 Hong Ning的查询是一个不错的开始,只是它将返回包含重复项和/或额外祖先的合并记录(例如,它还将返回具有祖先的人(“英格兰”,“法国”,“德国”,“荷兰”)和('英格兰”,“法国”,“英国”)。假设您只需要三个,而只需要三个,则需要以下查询:
SELECT Src.user_id
FROM yourtable Src
WHERE ancestry in ('England', 'France', 'Germany')
AND EXISTS (
SELECT user_id
FROM dbo.yourtable
WHERE user_id = Src.user_id
GROUP BY user_id
HAVING COUNT(DISTINCT ancestry) = 3
)
GROUP BY user_id
HAVING COUNT(DISTINCT ancestry) = 3