【问题标题】:Retrieving duplicate values in column SQL database检索列 SQL 数据库中的重复值
【发布时间】:2018-03-25 10:16:57
【问题描述】:

我有一个小型数据库,其中包含一个表格,其中包含电影每一行的信息(例如,电影名称、电影运行时间、电影分级),我还有一个单独的流派表,其中包含流派列表(恐怖、行动等)。

我有一个关联表,它将电影与流派联系起来(典型的行将包含该行的唯一 ID、流派 ID 和电影 ID)。

我写了一个查询,它会拉回用户观看过的所有类型;但是,它正在删除重复的行值,并给了我似乎不同的计数。

下面是SQL语句:

SELECT g.Type,
       g.Id
FROM GenreTable g
WHERE
  g.Id in (
    SELECT gma.GenreId
    FROM MovieGenreAssociationTable gma
    WHERE gma.MovieId in (
        SELECT uma.MovieSeriesId
        FROM UserMovieAssociationTable uma
        WHERE uma.UserId = '1'
      )
  );

这会返回用户观看过的所有类型,但我注意到它并没有带回我知道关联表中存在的重复项。

我如何获得这些重复项?

【问题讨论】:

  • 我是否正确理解一个动作可以有多种类型,例如一部电影既可以是恐怖片也可以是动作片?
  • 你是对的,一部电影可以有很多类型,而一个类型显然可以属于很多电影。

标签: sql duplicates


【解决方案1】:

您不是在单个表上创建 JOIN 而是 SELECT,因此它永远不会返回任何重复项,除非它们存在于 GenreTable 中。

如果您执行SELECT a FROM tbl WHERE b IN (1,1,1,1,1) 之类的操作,它将只返回一行,而不是五行。即使你有一个复杂的WHERE,它仍然是一个简单的IN 子句。

更新:关于 JOIN 的快速而肮脏的复习。

我实际上建议您查找 SQL 教程。 我不声明此说明的完整性 - 相反First google hitsecond hit

假设你有两个简单的表:

  a.id  a.a              b.id  b.b
  1     1                1     'Hello'
  2     1                2     'World'
  3     2                7     'foobar'
  4     3                

如果在a和b之间运行JOIN,ON(a.a = b.id),查询将选择a中的所有记录; 他们中的每一个将被加入到b中的所有匹配记录。这就是 JOIN 的用途。

在这种情况下,第二列和第三列总是相等的:

  1     1    1   'Hello'
  2     1    1   'Hello'
  3     2    2   'World'

请注意,a 的第四行被丢弃,因为它有 no 个匹配项,而 b 的第三行根本没有被选中。 b 的第二行被选中两次,因为 a 有两个元素匹配。

A LEFT JOIN 的工作方式相同,除了如果查询左侧(即表 a)没有匹配,就像第四行发生的那样,则选择该行都一样;但是来自 b 的额外字段被 NULL 替换。您会得到另一行,其中JOIN 子句ON(a.a = b.id) 实际上是错误的:

    4   3   NULL   NULL

(您可以使用它来选择在 b 中没有匹配项的 a 行:只需指定例如 WHERE b.primary_key_of_b IS NULL)。

您的情况

你应该这样做:

SELECT
  g.Type,
  g.Id
FROM GenreTable AS g
  JOIN MovieGenreAssociationTable AS gma ON (gma.GenreId = g.Id)
  JOIN UserMovieAssociationTable AS uma ON (uma.MovieSeriesId = gma.MovieId)
WHERE uma.UserId = 1;

然后您可以GROUP BY 例如输入和 ID 以获取每种类型的观看电影的 COUNT()

但是...

假设您有一个包含两行的 GenreTable(Id=123,Type="Science Fiction" 和 Id=456,Type="Comedy"),一个包含一行的 Movie 表(777,“Galactic Quest”),包含 (123, 777) 和 (456, 777) 的 MovieGenreAssociationTable,因为那部电影也是一部很棒的喜剧,最后用户 1 只看了电影 777。你会得到:

Genre                       gma         uma        Movie
123  "Science Fiction"      123, 777    777, 1     777, "Galaxy Quest"
456  "Comedy"               456, 777    777, 1     777, "Galaxy Quest"

并且会看到用户 1 看过两部电影 - 一部科幻片,一部喜剧片。

在这种情况下,您需要要么接受结果(他看了多少部喜剧?一部。一部科幻片?一部),或者进行更复杂的查询您必须确定哪个是主要类型。否则你会得到不合逻辑的结果(“有多少喜剧?一部。多少部电影?一部。那么非喜剧的数量是一减一,即零?不,又是一 - 等等,什么?”)。

在这种情况下,您可以为此目的在 MovieGenreAssociation 中添加一个列,即布尔列“IsMainGenre”。因此,当您想知道一个人看了多少部喜剧时,您可以按照上面的方法进行。但是,当您按类型划分电影时,添加 AND IsMainGenre=1 并计算“银河探秘”在科幻片中,而不是在喜剧或模仿中。

【讨论】:

  • 谢谢您,请您解释一下或提供一个链接,以便我可以了解这是什么类型的加入。我是 sql 新手,我有一张显示所有连接的图片(内、左、右等)。这是什么类型的连接:)?
  • 能否打扰您并询问我将如何将此 SQL 代码传输到我的 C# 应用程序中。我的应用程序在登录时存储 UserId,但我不确定如何获取此语句中使用的 GenreId 和 MovieId。我的命令阅读器说 hasRows 是真的,但阅读器不包含数据并抛出错误说“枚举没有产生结果”。我确定这是因为我没有设置流派和电影 ID。请问你能帮忙吗?
  • @AaronMoriarty 我正在更新我的答案。但规则是关闭 this 问题(如果没有用则接受或删除)并添加另一个(更好的是,首先研究 SO 并寻找与新问题类似的问题)。正如您在本题中所做的那样,新问题应该显示您所做的 - 查询和/或 C# 代码 - 可能还有您所期望的,以及您得到的。你可能想看看sscce.orgcatb.org/esr/faqs/smart-questions.html(你知道有一个数据库堆栈交换吗?;-))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-11
  • 2018-12-11
  • 2013-08-03
  • 1970-01-01
  • 2015-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多