2017-02-10 32 views
0

我发现了很多与我有关的问题,但仍然无法解决这个问题。Mysql select包含字符串+特定int列的比较

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

表结构示例:

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

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

但是,如果两个不同的行具有包含字符串的VALUE列(如示例中的字符串是“冰”),我想检索与该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+""; 
  • 我不知道我应该怎样包括“喜欢”来检查包含字符串时,我有一个像“+字符串+”的价值观。
  • 我不知道如何将具体的INT列与特定的VALUE列进行比较,当我有多个VALUE包含该字符串的行时。
+0

你确定使用MySQL吗? –

回答

1

首先使用UNION ALL标准化表格。这意味着每一行都必须分成三份。每组一个(INT_1 VALUE1,INT_2 VALUE2,INT_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

现在把它放在一个子查询和搜索使用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%' 

结果:

| 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

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

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 
+0

经过一段时间才得到它的工作。谢谢。 – DigitalEvolution

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; 
+0

谢谢。仍在学习... – DigitalEvolution

+0

这是否适合你? –

+0

没试过。我做了上面的答案 – DigitalEvolution