【问题标题】:Select rows where a field is associated with more than one predefined value [duplicate]选择字段与多个预定义值相关联的行[重复]
【发布时间】:2018-12-05 20:11:48
【问题描述】:

我很难为这个问题选择一个标题。我不确定它是否准确地描述了我想要的东西,所以如果你能帮助改进标题而不是投反对票,我将不胜感激。 :)

我有以下(示例)表格:

USERS:
+----------+
|    id    |
+----------+
|     1    |
------------
|     3    |
------------
|     4    |
+----------+
URLS:
+----------+----------+
|    id    |    url   |
+----------+----------+
|     1    |   a.com  |
-----------------------
|     1    |   b.com  |
-----------------------
|     1    |   d.com  |
-----------------------
|     2    |   a.com  |
-----------------------
|     2    |   e.com  |
-----------------------
|     3    |   a.com  |
-----------------------
|     3    |   e.com  |
-----------------------
|     3    |   f.com  |
-----------------------
|     3    |   g.com  |
-----------------------
|     4    |   a.com  |
-----------------------
|     4    |   e.com  |
+----------+----------+

我想从URLS 中选择与USERS 中至少两个ID 相对应的所有URL。因此,例如,使用这些示例表进行此类查询的结果:

+----------+
|    url   |
+----------+
|   a.com  | <- associated with ids: 1, 3, 4
------------
|   e.com  | <- associated with ids: 3, 4
+----------+

如您所见,例如,b.com1 相关联,后者位于 USERS 表中。但是,因为它与 USERS 中的任何其他 id 都没有关联,所以它不在结果中。我怎样才能做到这一点?

【问题讨论】:

  • 您可以根据需要使用 STUFF()。
  • @ZekiGumus - 你能详细说明一下吗?
  • 我正在准备样品
  • 只需在表之间进行内部连接,以限制用户中具有匹配 ID 的记录,然后 GROUP BY url 和 HAVING COUNT(1) > 1。只需查找 HAVING 子句,它就会变得明显。
  • SO 不是免费的编码服务网站。你试过什么???发布您的查询。如果您还没有尝试过任何事情,那就开始工作吧。

标签: sql sql-server


【解决方案1】:

如果最小值不等于最大值,您将有多个与url 关联的 id,我们可以通过执行inner join 排除不在USERS 表中的ids,所以也许像这样的

select url
from URLS as a
inner join USERS as b
on a.id=b.id
group by url
having max(b.id)<>min(b.id)

【讨论】:

  • 我不确定这是否会比 COUNT(DISTINCT id) > 1 执行得更好或更差,但它会达到预期的结果。唯一需要额外考虑的是,如果 url 中的 ID 列与用户之间没有约束,那么如果您想忽略来自没有匹配 USERS 记录的 URL 中的记录,则需要 JOIN。
  • 要填写问题的确切措辞,需要加入Users。问题要求“与用户中的至少两个 id 相对应的 URL”。您的代码可能会返回对应于两个 id 的 URL,即使它们根本不在 Users 中。
  • @MattCremeens 仅当我们可以假设 URLs 中的所有 id 也都在 Users 中时才会成立,但在示例数据中并非如此。
  • @TabAlleman 这是一个有效点。我会编辑。
【解决方案2】:

你可以使用EXISTS()作为

SELECT Url
FROM Urls T
WHERE EXISTS(
              SELECT 1
              FROM Urls
              WHERE ID != T.ID
                    AND
                    Url = T.Url
            )
GROUP BY Url;

或者

SELECT T1.Url
FROM Urls T1 JOIN Urls T2
ON T1.ID != T2.ID
AND T1.Url = T2.Url
GROUP BY T1.Url;

更新:

因为你需要加入Users table

SELECT T1.Url
FROM Urls T1 INNER JOIN Users T2
ON T1.ID = T2.ID
WHERE EXISTS(
              SELECT 1
              FROM Urls
              WHERE ID != T1.ID
                    AND
                    Url = T1.Url
            )
GROUP BY T1.Url;

SELECT T1.Url
FROM Urls T1 INNER JOIN Urls T2
ON T1.ID != T2.ID
AND T1.Url = T2.Url
INNER JOIN Users U ON T1.ID = U.ID
GROUP BY T1.Url;

Demo

【讨论】:

  • 谢谢!但是在这个选择中,哪里有针对USERS 表的检查?
  • 好吧@Sipo 检查更新。
  • 谢谢。我得到 0 个结果。 :(
  • 好吧,我不这么认为@Sipo 你可以在那里查看演示。
  • 你说得对,我遇到了配置问题。让我现在测试一下。
【解决方案3】:

如果您想在同一列中查看所有关联的 Id,可以使用 STUFF() 。这是您的示例:

--DROP TABLE Users;
CREATE TABLE Users
(
    id  INT
);


--DROP TABLE Urls;
CREATE TABLE Urls
(
    id  INT
    ,Url    VARCHAR(100)
);

INSERT INTO Users VALUES(1),(2),(3),(4)
INSERT INTO URLs  VALUES
 (1,'a.com')
,(1,'b.com')
,(1,'d.com')
,(2,'a.com')
,(2,'e.com')
,(3,'a.com')
,(3,'e.com')
,(3,'f.com')
,(3,'g.com')
,(4,'a.com')
,(4,'e.com')

SELECT *,
        STUFF((SELECT distinct ',' + CAST(ID AS VARCHAR)
                    from URLs U2
                    WHERE U1.Url=U2.Url
                    AND EXISTS (SELECT 1 FROM Users US WHERE U2.id=US.id)
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

FROM 
    (SELECT DISTINCT Url FROM Urls) U1

【讨论】:

  • 我认为 OP 只想要与多个用户相关联的 URL 值......我认为他们甚至不关心用户是什么,只是有多个用户。
  • 我已将 EXISTS() 添加到这些内容中。所以,现在它也与用户相关。
  • 谢谢。我已经尝试过你的解决方案。结果,我得到了所有 URL,而不仅仅是 a.come.com
  • @ZekiGumus 我很确定你误解了这个问题。
  • @TabAlleman 你是对的。无论如何,它已经被标记为重复。谢谢。
猜你喜欢
  • 2020-02-01
  • 2021-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-01
相关资源
最近更新 更多