我有以下查询返回重复的标题,但:id
是nil
:
Movie.select(:title).group(:title).having("count(*) > 1")
[#<Movie:0x007f81f7111c20 id: nil, title: "Fargo">,
#<Movie:0x007f81f7111ab8 id: nil, title: "Children of Men">,
#<Movie:0x007f81f7111950 id: nil, title: "The Martian">,
#<Movie:0x007f81f71117e8 id: nil, title: "Gravity">]
我尝试将:id
添加到select和group,但它返回一个空数组。如何归还整个电影记录,而不仅仅是标题?
答案 0 :(得分:15)
以SQL-y方式
首先,让我们解决SQL中的问题,以便特定于Rails的语法不会欺骗我们。
这个问题非常明确:Finding duplicate values in a SQL Table
KM的答案(排名第二,目前尚未选中),符合您返回所有重复记录及其ID的标准。我已修改 KM的 SQL以匹配您的表...
SELECT
m.id, m.title
FROM
movies m
INNER JOIN (
SELECT
title, COUNT(*) AS CountOf
FROM
movies
GROUP BY
title
HAVING COUNT(*)>1
) dupes
ON
m.title=dupes.title
INNER JOIN ( )
内的部分基本上就是你已经生成的部分。重复标题和计数的分组表。诀窍是JOIN
将其添加到未经修改的movies
表中,该表将排除任何在dupes查询中没有匹配项的电影。
为什么在Rails中生成这么难?最棘手的部分是,因为我们JOIN
movies
到movies
,我们必须在上面的查询中创建表别名(m
和dupes
)。
可悲的是,Rails没有提供任何声明这些别名的干净方法。一些参考文献:
幸运的是,既然我们手头有SQL,我们可以使用.find_by_sql
方法......
Movie.find_by_sql("SELECT m.id, m.title FROM movies m INNER JOIN (SELECT title, COUNT(*) FROM movies GROUP BY title HAVING COUNT(*)>1) dupes ON m.first=.first")
因为我们正在调用Movie.find_by_sql
,所以ActiveRecord假设我们的手写SQL可以捆绑到Movie
个对象中。它不会按摩或产生任何东西,这可以让我们做别名。
这种方法有其缺点。它返回一个数组而不是ActiveRecord Relation,这意味着它不能与其他范围链接。并且,in the documentation for the find_by_sql
method,我们得到额外的沮丧......
这应该是最后的手段,因为使用例如特定于MySQL的术语会阻止您使用该特定数据库引擎,或者如果您切换引擎则需要更改您的呼叫。
Rails-y Way
真的,上面的SQL是做什么的?它获得了不止一次出现的名称列表。然后,它将该列表与原始表匹配。所以,让我们使用Rails来做到这一点。
titles_with_multiple = Movie.group(:title).having("count(title) > 1").count.keys
Movie.where(title: titles_with_multiple)
我们调用.keys
,因为第一个查询返回一个哈希值。钥匙是我们的头衔。 where()
方法可以采用数组,我们已经为它提供了一系列标题。赢家。
你可以说一行Ruby优于两行。如果那一行Ruby中嵌入了一个不道德的SQL字符串,它真的有多优雅吗?
希望这有帮助!
答案 1 :(得分:0)
您可以尝试在import Foundation
import Realm
class NotSureItem: RLMObject {
dynamic var title = ""
dynamic var description = ""
dynamic var dateTime = NSDate()
}
中添加id
:
select