简体   繁体   English

MySQL选择包含字符串的行+特定的int列比较

[英]Mysql select row containing string + specific int column comparison

I have found numerous questions related to mine but still can't solve this issue. 我发现了许多与我有关的问题,但仍然无法解决这个问题。

In my table there are 3 columns filled with integer values and 3 columns with string values. 在我的表中,有3列填充整数值,而3列填充字符串值。 I have several rows. 我有几行。

Table structure example: 表结构示例:

  INT_1 | INT_2 | INT_3 | VALUE1 | VALUE2 | VALUE3
   33   |  25   |   10  | "nice"| "hello"| "goodbye"
  ---------------------------------------------------
   10   |  15   |   28  | "dice"| "hay"  | "bird"

I have a string that I use to select the rows based on the VALUE columns. 我有一个用于根据VALUE列选择行的字符串 The way I want to select it is with inclusion which means if the string is "llo" I should get the row where at least one of the values (VALUE,VALUE2,VALUE3) contains "llo" (would select the row with "hello" in VALUE2, for example). 我要选择的方式是包含,这意味着如果字符串是“ llo”,我应该获得其中至少一个值(VALUE,VALUE2,VALUE3)包含“ llo”的行(将用“ hello选择行”例如在VALUE2中)。

However if two different rows have VALUE columns that contain the string (like in the example if the string is "ice") I want to retrieve the row where the INT column associated to that VALUE is higher. 但是,如果两个不同的行都有包含该字符串的VALUE列(例如在示例中,如果字符串为“ ice”),我想检索与该VALUE关联的INT列较高的行。 In the example since the string was compared to VALUE1 I should compare INT_1 of the upper column with INT_1 of the lower column and retrieve the row where INT_1 is higher. 在示例中,由于将字符串与VALUE1进行了比较,因此我应该将上一列的INT_1与下一列的INT_1进行比较,并检索INT_1较高的行。 (INT_1 -> VALUE1, INT_2 -> VALUE2, INT_3 -> VALUE3). (INT_1-> VALUE1,INT_2-> VALUE2,INT_3-> VALUE3)。

Well not much but I could figure this myself: 很好,但我自己可以解决这个问题:

 SELECT * FROM my_table WHERE VALUE1 = "+string+" OR VALUE2= "+string+" OR VALUE3= "+string+"";
  • I am not sure how should I include "LIKE" to check for containing string when I have the values like "+string+". 当我具有“ + string +”之类的值时,我不确定如何包含“ LIKE”来检查是否包含字符串。
  • I don't know how to compare the specific INT column with the specific VALUE column when I have more than one row where VALUE contains the string. 当我有多于VALUE包含字符串的行时,我不知道如何将特定的INT列与特定的VALUE列进行比较。

First normalize your table using UNION ALL . 首先使用UNION ALL标准化表。 That means every row have to be splitted into three. 这意味着每一行都必须分成三行。 One for each group ( INT_1 VALUE1 , INT_2 VALUE2 , INT_3 VALUE3 ). 每个组一个( INT_1 VALUE1INT_2 VALUE2INT_3 VALUE3 )。 Since you don't have an explicit primary key, you need to include all columns to identify the source row. 由于您没有显式主键,因此需要包括所有列以标识源行。

select t.*, 1 as position, INT_1 as i, VALUE1 as v from my_table t
union all
select t.*, 2 as position, INT_2 as i, VALUE2 as v from my_table t
union all
select t.*, 3 as position, INT_3 as i, VALUE3 as v from my_table t

Result: 结果:

| INT_1 | INT_2 | INT_3 | VALUE1 | VALUE2 |  VALUE3 | position |  i |       v |
|-------|-------|-------|--------|--------|---------|----------|----|---------|
|    33 |    25 |    10 |   nice |  hello | goodbye |        1 | 33 |    nice |
|    10 |    15 |    28 |   dice |    hay |    bird |        1 | 10 |    dice |
|    33 |    25 |    10 |   nice |  hello | goodbye |        2 | 25 |   hello |
|    10 |    15 |    28 |   dice |    hay |    bird |        2 | 15 |     hay |
|    33 |    25 |    10 |   nice |  hello | goodbye |        3 | 10 | goodbye |
|    10 |    15 |    28 |   dice |    hay |    bird |        3 | 28 |    bird |

http://sqlfiddle.com/#!9/9086d5/1 http://sqlfiddle.com/#!9/9086d5/1

Now put it in a subquery and search for your string in the v column using WHERE v LIKE '%ice%' . 现在将其放在子查询中,并使用WHERE v LIKE '%ice%'v列中搜索您的字符串。

select *
from (
    select t.*, 1 as position, INT_1 as i, VALUE1 as v from my_table t
    union all
    select t.*, 2 as position, INT_2 as i, VALUE2 as v from my_table t
    union all
    select t.*, 3 as position, INT_3 as i, VALUE3 as v from my_table t
) n
where v like '%ice%'

Result: 结果:

| INT_1 | INT_2 | INT_3 | VALUE1 | VALUE2 |  VALUE3 | position |  i |    v |
|-------|-------|-------|--------|--------|---------|----------|----|------|
|    33 |    25 |    10 |   nice |  hello | goodbye |        1 | 33 | nice |
|    10 |    15 |    28 |   dice |    hay |    bird |        1 | 10 | dice |

http://sqlfiddle.com/#!9/9086d5/4 http://sqlfiddle.com/#!9/9086d5/4

Last step - Pick the row with the highest value in i using ORDER BY i DESC LIMIT 1 : 最后一步-使用ORDER BY i DESC LIMIT 1 i具有最高值的行:

select `INT_1`, `INT_2`, `INT_3`, `VALUE1`, `VALUE2`, `VALUE3`
from (
    select t.*, 1 as position, INT_1 as i, VALUE1 as v from my_table t
    union all
    select t.*, 2 as position, INT_2 as i, VALUE2 as v from my_table t
    union all
    select t.*, 3 as position, INT_3 as i, VALUE3 as v from my_table t
) n
where v like '%ice%'
order by i desc
limit 1

Result: 结果:

| INT_1 | INT_2 | INT_3 | VALUE1 | VALUE2 |  VALUE3 |
|-------|-------|-------|--------|--------|---------|
|    33 |    25 |    10 |   nice |  hello | goodbye |

http://sqlfiddle.com/#!9/9086d5/5 http://sqlfiddle.com/#!9/9086d5/5

The query can be shorter if you use a HAVING clause instead of WHERE , so you don't need to use a subquery. 如果您使用HAVING子句而不是WHERE ,则查询可以更短,因此您不需要使用子查询。 But then you get two columns ( i and v ), that you might not need. 但是随后您将获得可能不需要的两列( iv )。 On the other hand, they might be the only columns you need. 另一方面,它们可能是您唯一需要的列。

select t.*, INT_1 as i, VALUE1 as v from my_table t union all
select t.*, INT_2 as i, VALUE2 as v from my_table t union all
select t.*, INT_3 as i, VALUE3 as v from my_table t
having v like '%ice%'
order by i desc
limit 1

And one more modification which might improve the performance a little bit: 还有一个可能会稍微提高性能的修改:

select t.*, INT_1 as i from my_table t where VALUE1 like '%ice%' union all
select t.*, INT_2 as i from my_table t where VALUE2 like '%ice%' union all
select t.*, INT_3 as i from my_table t where VALUE3 like '%ice%'
order by i desc
limit 1

This is a horrible data structure. 这是一个可怕的数据结构。 But here is one way to do this? 但是这里有一种方法可以做到这一点?

SELECT t.*
FROM my_table t
WHERE VALUE1 LIKE '%string%' OR VALUE2 LIKE '%string%' OR VALUE3 LIKE '%string%'
ORDER BY greatest( (case when VALUE1 LIKE '%string%' then int_1 else -1 end),
                   (case when VALUE1 LIKE '%string%' then int_2 else -1 end),
                   (case when VALUE1 LIKE '%string%' then int_3 else -1 end) ) desc
LIMIT 1;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM