【问题标题】:Firebird remove duplicate ROWS on SELECT LIST subqueryFirebird 删除 SELECT LIST 子查询中的重复行
【发布时间】:2017-09-25 13:30:48
【问题描述】:

我正在使用 Firebird 数据库 v2.5,但无法从查询中删除重复行:

SELECT  DISTINCT u.id_user, 
        (SELECT LIST(g.id_user) 
         from gen g 
         where g.id_user=u.id_user 
         GROUP BY id_user) as list_g_user
FROM users u 
where  u.id_user = 1 
  INNER JOIN ...

这是我的结果:

 id_user  |  list_g_user 
===================================
1         |  437,499,718,739,835,865
1         |  437,499,718,739,835,865
1         |  437,499,718,739,835,865
1         |  437,499,718,739,835,865

第二列结果list_g_user是BLOB类型。

相同的结果和多行。 谁能解释一下原因?

这是函数参考:Firebird Documentation: LIST()

【问题讨论】:

  • From here "SELECT DISTINCT、ORDER BY 和 GROUP BY 作用于 BLOB ID,而不是内容。这使它们变得无用..." 它继续说 "GROUP BY奇怪的是,如果它们相邻,它会将相等的行组合在一起,但如果它们分开,则不会。”所以也许试试GROUP BY id_user, list_g_user 看看能不能解决问题。
  • 为什么需要内连接?
  • 你为什么不使用:select u.id_user, list(g.id_user) from users u join gen g on .. where ... group by u.id_user

标签: sql firebird aggregation firebird2.5


【解决方案1】:

正如JNevilldistinct 和 blob does not behave as expected in Firebird 已经指出的那样:它比较 blob id(指向 blob 的“指针”),而不是 blob 的内容,并且list() 会生成 blob。

要解决此问题,有几种可能的解决方案:

  1. list() 的结果转换为varchar 以便正确比较,例如:

    SELECT cast(LIST(g.id_user) as varchar(100)) ...
    

但这确实意味着列表的字符长度不应超过 varchar 长度(本例中为 100)。

  1. 您在查询中使用inner join 而不使用联接表中的任何内容,似乎表明您仅将联接用作存在性检查。用 exists 检查替换该连接:

    SELECT u.id_user, 
            (SELECT LIST(g.id_user) 
             from gen g 
             where g.id_user=u.id_user 
             GROUP BY id_user) as list_g_user
    FROM users u 
    where  u.id_user = 1 
    and exists (select * from <currently joined table> x where x.id_user = u.id_user)
    
  2. 正如 JNevill 在 cmets 中所建议的那样,您可以尝试在顶级查询中使用 group by id_user,但这可能并不总是有效,因为它依赖于 blob id 相邻。在不能使用group by的情况下,这不是一个可行的解决方案:

    SELECT  DISTINCT u.id_user, 
            (SELECT LIST(g.id_user) 
             from gen g 
             where g.id_user=u.id_user 
             GROUP BY id_user) as list_g_user
    FROM users u 
    where  u.id_user = 1 
      INNER JOIN ...
    group by u.id_user
    

【讨论】:

    【解决方案2】:
    SELECT  DISTINCT u.id_user,
            CAST(SUBSTRING((SELECT LIST(g.id_user)
             from gen g
             where g.id_user=u.id_user
             GROUP BY id_user) FROM 1 FOR 1000) AS VARCHAR(1000)) as list_g_user
    FROM users u
    where  u.id_user = 1
      INNER JOIN ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-09
      • 1970-01-01
      • 2014-07-09
      • 2021-11-07
      • 2021-09-24
      • 1970-01-01
      • 1970-01-01
      • 2020-02-17
      相关资源
      最近更新 更多