【问题标题】:How to merge lines in an SQL query?如何在 SQL 查询中合并行?
【发布时间】:2010-07-07 14:46:29
【问题描述】:

我的桌子是这样的

id | string | foreign_id
---------------------------
1  | house  | 5
2  | garden | 6
3  | window | 5
...

我有一个字符串数组,我想获取与数组中的 all 元素匹配的所有外来 id。所以我有一个像这样的数组 [house, window] 然后我想得到 5。字符串数组最多可以有 10 个元素。

合适的sql语句长什么样?

【问题讨论】:

  • 这是作业吗?如果是,请这样标记。
  • 您使用的是哪个 SQL 系统? MySQL?微软 SQL? SQLite?甲骨文?等等?
  • 我使用 MySQL,大学作业需要这个。

标签: sql merge lines


【解决方案1】:

尝试类似:

select foreign_id 
from your_table
where string in ('house', 'window')
group by foreign_id
having count(distinct string) = 2;

- 假设生成查询的任何东西都可以计算请求的不同字符串的数量。

(在 cmets 之后编辑)

【讨论】:

  • HAVING COUNT(*) 有误报的风险。 IE:foreign_id 为 5,其中字符串值为“house”的两条记录是有效的。
  • 正如我在帖子中所说的,也存在误报。 foreign_id 为 5 的两条记录的字符串值为“house”,加上一条字符串值为“window”的记录将是无效的。
  • 对不起,应该有 count(distinct string) = 2 - 现在已经编辑了答案。
【解决方案2】:

假设您希望foreign_id 同时匹配“house”和“window”,请使用:

  SELECT t.foreign_id
    FROM YOUR_TABLE t
   WHERE t.string IN ('house', 'window')
GROUP BY t.foreign_id
  HAVING COUNT(DISTINCT t.string) = 2

HAVING 计数必须等于 IN 子句中定义的数值。

字符串数组最多可以有 10 个元素。

这需要使用动态 SQL。我会提供一个例子,但你没有提到你正在使用什么数据库......

【讨论】:

  • 这将匹配一个foreign_id,它只有一个对应的“house”,而不是“window”。
【解决方案3】:
select string, foreign_id
from table
group by foreign_id

【讨论】:

    【解决方案4】:

    动态生成查询,为每个数组元素添加一次注释行:

    Select distinct foreign_id
     from myTable
    where 1=1
      --add the following line once for each array element
    and foreign_id in (select foreign_id from myTable where string = 'value')
    

    所以给出你的例子,查询将是

    Select distinct foreign_id
     from myTable
    where 1=1
    and foreign_id in (select foreign_id from myTable where string = 'house')
    and foreign_id in (select foreign_id from myTable where string = 'window')
    

    这应该会返回您要查找的内容。

    有什么问题吗?

    // 1=1 只是为了让动态部分每次都相同。我会排除 1=1 并让第一个条目跳过“和”

    【讨论】:

    • 感谢您的主观分析。
    【解决方案5】:

    @Mark Ba​​nnister 很接近,但是当字符串和foreign_id 重复时,他会失败。这行得通,但我已经有好几年没有用 SQL 做任何有用的事情了,所以可能有更好的方法。

    SELECT foreign_id FROM (
       SELECT distinct string, foreign_id FROM your_table
          WHERE string in ('house', 'window')) as T  
    GROUP BY T.foreign_id HAVING count(foreign_id) = 2;
    

    与 Mark 一样,我假设您可以动态填充 in 子句以及 having 子句的 RHS。存储过程可能会有所帮助。

    【讨论】:

    • Mark Ba​​nnisters 的回答更好——它只会在桌子上使用一次。不需要派生表/内联视图...此外,HAVING COUNT 应该在不同的值上——而不是 foreign_id 列;)
    • have 子句可以正常工作因为我使用子选择。我看到你已经更新了你的答案,现在看起来。
    • @Mark Peters:你没有抓住重点——没有必要在内部查询中返回 string 列(除了 GROUP BY 中的 DISTINCT 是没用的)。这一切都可以在没有派生表的情况下完成。而且您的 COUNT 仍然引用了错误的列...
    • 不,我没有错过重点。我知道它可以在没有嵌套选择的情况下完成,但是由于您已经在自己的答案中对其进行了改进,所以我认为这里没有必要这样做。我在 group by 中没有 DISTINCT,所以我不确定你在说什么,并且 count 使用 foreign_id 还是 * 都没有关系,因为它是单列视图。你不能真的说任何 SQL 是“错误的”,除非你能举例说明它什么时候会返回错误的结果。这样做,我会认真对待你。
    • @Mark Peters:如果您查看解释计划,使用此查询将需要两次通过 - 第一次处理内部查询,第二次处理外部查询。因为在运行外部查询时没有可以利用的索引,所以可以保证是表扫描。虽然查询返回正确的值,但这并不是最有效的方法。您的查询仍会在内部查询中列出 DISTINCT 关键字...其中还定义了 GROUP BY 子句。 GROUP BY 意味着只返回不同的字符串值(不需要作为列) - 不需要 DISTINCT。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多