SQL选择和组记录具有不同顺序的相同单词

时间:2015-05-19 19:47:56

标签: sql regex postgresql group-by sql-order-by

我在表格中有以下值:

表水果

id | name                        | price
-----------------------------------------
 1 | 'APPLE BANANA ORANGE'       | 12.00
 2 | 'BANANA ORANGE APPLE'       |  4.00
 3 | 'ORANGE APPLE BANANA'       | 10.00
 4 | 'LEMON APPLE BANANA ORANGE' |  7.00
 5 | 'APPLE LEMON BANANA ORANGE' |  8.00

我想选择3个第一行的所有值,而我所拥有的只是包含' APPLE BANANA ORANGE'

的文字

示例

SELECT * 
FROM fruits 
WHERE name IN 
('APPLE BANANA ORANGE','BANANA ORANGE APPLE','ORANGE APPLE BANANA')

问题在于,这些价值来自另一张表,我正在寻找一种方法来生成可能值的不同组合

也许使用功能:

SELECT * 
FROM fruits f 
INNER JOIN order o ON o.name IN some_function(f.name)

也许使用一些正则表达式:

SELECT * 
FROM fruits f 
INNER JOIN order o ON o.name ~ '(?=' || f.name || ')'

我试图使用在互联网上找到的一些使用环视的正则表达式,它们带来包含这三个单词的所有值,但包括也有更多单词的单词。喜欢&LAMON APPLE BANANA ORANGE'和' APPLE LEMON BANANA ORANGE'

另一件事是我想将这些结果分组,无论它们看起来像

SELECT sum(price) 
FROM fruits f 
INNER JOIN order o ON o.name ~ '(?=' || f.name || ')'
GROUP BY somefunction(name);

谢谢你的帮助

Marcel Isaac

更新

我创建了一个分割字符串内容的函数,命令单词并返回带有序词的新字符串

CREATE OR REPLACE FUNCTION order_words(txt character varying) 
returns character varying as
$BODY$
DECLARE 
    tmp character varying;
BEGIN
    SELECT string_agg(t,' ') 
    INTO tmp
    FROM (
      SELECT rstt 
      FROM regexp_split_to_table(txt, ' ') rstt 
      ORDER BY rstt) t; 

    RETURN tmp;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

对值执行时,它始终返回相同的字符串

select order_words('APPLE BANANA ORANGE');
    order_words     
---------------------
APPLE BANANA ORANGE
(1 row)

select order_words('BANANA ORANGE APPLE');
    order_words     
---------------------
APPLE BANANA ORANGE
(1 row)

select order_words('ORANGE APPLE BANANA');
    order_words     
---------------------
APPLE BANANA ORANGE
(1 row)

现在我可以编写我的代码

SELECT order_words(name),sum(price) 
FROM fruits f 
INNER JOIN order o ON order_words(o.name) = order_words(f.name)
GROUP BY order_words(name);

我将测试性能

1 个答案:

答案 0 :(得分:1)

不确定这是否比您的解决方案更快:

select f.*
from fruits f
  join orders o 
    on string_to_array(f.name, ' ') @> string_to_array(o.name, ' ')
   and cardinality(string_to_array(f.name, ' ')) = cardinality(string_to_array(o.name, ' '));

我们的想法是将两个值分成数组并检查它们是否重叠。但是因为"重叠"并不意味着所有元素都相等,我也在比较数组的长度。如果长度相等重叠,则所有元素都相等。

表达式string_to_array(f.name, ' ')可以编入索引,@>运算符甚至可以使用GIN索引。