【问题标题】:Fetch Data from table 1 based on text in a column and a different text in a column of different table根据列中的文本和不同表的列中的不同文本从表1中获取数据
【发布时间】:2015-07-13 00:33:48
【问题描述】:

我有两张桌子。

表 1:

T1id1(pk) col1 col2 col3

表 2:

id(pk) T1id1(FK) col1 col2 col3

我从用户那里得到两个文本,其中 table1.col1 有一些文本(如 %text1%),同样对于 table2 col1,我得到另一个不等于 text1 的文本(如 %text2%)。

我需要从 table1 中获取一组一百条记录,其中 table2 col1 包含 text2 AND Table1 col1 包含 text1。当查询下一组 100 时,我不应该得到第一组 100 中的任何记录。

以下是我编写的示例查询,但它失败了。我正在使用 Apache Phoenix,并且任何 SQL 兼容数据库中的解决方案都可以。

SELECT * FROM table1 WHERE T1id1 IN (select T1id1 from ndm.table1 where
T1id1 NOT IN( select T1id1 from table1 where T1id1 in (select distinct
T1id1(FK) from table2 WHERE table2.col1 like '%text2%' )LIMIT     100)     AND T1id1 in (select distinct T1id1(FK) from table2 WHERE     
table2.col1 like '%text2%' limit 200) and table1.col1 ilike '%text2%' LIMIT 100);

【问题讨论】:

  • 最好包含样本数据和预期输出
  • 您可能需要在外部查询中进行排序 - 并从那里继续。如果这对您不起作用,您可能需要考虑(为此特定目的)特定标志。在任何情况下:您能确定不会有任何并发​​更新,这会在已显示的记录和仍将显示的记录之间移动?

标签: sql phoenix


【解决方案1】:

鉴于您使用ILIKE,您可能尝试过使用 PostgreSQL - 它似乎允许在单个语句中使用多个 LIMITs。 (从这个SQL Fiddle来看,与你的陈述相比,ndm.table1被改为table1(FK)下降了两次)。

虽然调整了

SELECT
  *
FROM table1
WHERE
  T1id1 IN
    (select
       T1id1
     from table1
     where
       T1id1 NOT IN
         (select T1id1
          from table1
          where
            T1id1 in
              (select distinct
                 T1id1
               from table2
               WHERE
                 table2.col1 like '%text2%'
              )
          LIMIT 100
         )
     AND T1id1 in
       (select distinct
          T1id1
        from table2
        WHERE
          table2.col1 like '%text2%'
        limit 200
       )
     and
     table1.col1 ilike '%text2%'
     LIMIT 100
    )
;

似乎被 PostgreSQL 接受——它不太可能返回预期的结果:

使用 LIMIT 时,使用 ORDER BY 子句很重要 将结果行限制为唯一的顺序。否则你会得到 查询行的不可预测的子集。你可能会问 第 10 到第 20 行,但是第 10 到第 20 行是什么 订购?排序是未知的,除非您指定了 ORDER BY。

来自 PostgreSQL 9.3 文档7.6 LIMIT and OFFSET

从你的问题描述开始(并在你的陈述中查看一些细节),类似于

SELECT
  T1.*
FROM Table1 T1
JOIN Table2 T2
  ON T1.t1id1 = T2.t1id1
  AND INSTR(T1.col1, 'teXT1')
  AND INSTR(T2.col1, 'teXT2')
ORDER BY T1.t1id1, T2.id
LIMIT 1 OFFSET 0
;

SELECT
  T1.*
FROM Table1 T1
JOIN Table2 T2
  ON T1.t1id1 = T2.t1id1
  AND INSTR(T1.col1, 'teXT1')
  AND INSTR(T2.col1, 'teXT2')
ORDER BY T1.t1id1, T2.id
LIMIT 1 OFFSET 1
;

SELECT DISTINCT
  T1.*
FROM Table1 T1
JOIN Table2 T2
  ON T1.t1id1 = T2.t1id1
  AND INSTR(T1.col1, 'teXT1')
  AND INSTR(T2.col1, 'teXT2')
ORDER BY T1.t1id1, T2.id
LIMIT 1 OFFSET 0
;

应该让你进入正确的方向。您是否需要DISTINCT 在某种程度上取决于您的数据——但更重要的是取决于您的整体需求。请比较 SQL Fiddle 下面的语句 1 到 4 和 5 到 7 以了解效果。

主要是将LIMITOFFSET 结合起来——您似乎试图找到自己的替代品。

除此之外:通配符位于字符串的两端,INSTRLIKE 具有相同的选择性 - 但在某些情况下它更有效...

记住您使用了ILIKE:只要比较中不涉及二进制字符串,LIKEINSTR 在 MySQL 中都不区分大小写。

查看实际操作:SQL Fiddle

如果需要调整/进一步详细信息,请发表评论。

【讨论】:

  • 明天我会尽量让你知道
  • 是的,Abecee,实际上,我正在使用 Apache Phoenix。我尝试获取通用 SQL 查询,以便我可以使用它们作为参考来实现我的解决方案,以便我也学习。当我问这个查询时,我们使用的是 4.3.1 版本的 phoenix,其中 instr 函数不存在。但是现在我们升级到 4.5,我可以使用你的建议并让它发挥作用。再次非常感谢。
  • 嗯 - 这就是为什么指定你的环境是有意义的。另一方面,随意使用 cmets 来提供更多细节。在这里,使用INSTR 是一个偏好问题。它可以很容易地被替换为,例如,LIKE。回头见。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-28
  • 2013-03-28
  • 2015-03-11
相关资源
最近更新 更多