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

时间:2017-02-10 23:20:48

标签: javascript mysql sql database

我发现了很多与我有关的问题,但仍然无法解决这个问题。

在我的表中有3列填充整数值,3列填充字符串值。我有好几行。

表结构示例:

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

我有一个字符串,用于根据VALUE列选择行。我想要选择它的方式是包含,这意味着如果字符串是“llo”我应该得到至少其中一个值(VALUE,VALUE2,VALUE3)包含“llo”的行(会在VALUE2中选择“hello”行,例如)。

但是,如果两个不同的行具有包含字符串的VALUE列(如示例中的字符串是“ice”),我想检索与该VALUE关联的INT列更高的行。在示例中,因为字符串与VALUE1进行比较,我应该将上一列的INT_1与下一列的INT_1进行比较,并检索INT_1更高的行。 (INT_1 - > VALUE1,INT_2 - > VALUE2,INT_3 - > VALUE3)。

唔不多但我自己也能想到这个:

 SELECT * FROM my_table WHERE VALUE1 = "+string+" OR VALUE2= "+string+" OR VALUE3= "+string+"";
  • 我不知道如果我有“+ string +”这样的值,我应该怎么包含“LIKE”来检查包含字符串。
  • 当我有多行VALUE包含字符串时,我不知道如何比较特定的INT列和特定的VALUE列。

2 个答案:

答案 0 :(得分:1)

首先使用UNION ALL规范化您的表格。这意味着每行必须分成三行。每组一个(INT_1 VALUE1INT_2 VALUE2INT_3 VALUE3)。由于您没有显式主键,因此需要包括所有列以标识源行。

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

结果:

| 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

现在将其放入子查询中,并使用vWHERE v LIKE '%ice%'列中搜索您的字符串。

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%'

结果:

| 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

最后一步 - 使用i选择ORDER BY i DESC LIMIT 1中值最高的行:

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

结果:

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

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

如果使用HAVING子句而不是WHERE,则查询可以更短,因此您不需要使用子查询。但是,您可能会得到两列(iv),您可能不需要这些列。另一方面,它们可能是您需要的唯一列。

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

还有一项修改可能会稍微提高性能:

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

答案 1 :(得分:1)

这是一个糟糕的数据结构。但这是一种方法吗?

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;