【问题标题】:FIND_IN_SET with comma seperated values for sorting condition带有逗号分隔值的 FIND_IN_SET 用于排序条件
【发布时间】:2014-08-09 09:52:35
【问题描述】:

我正在使用find_in_set 使用以下查询获取数据,它工作正常。

SELECT * 
FROM A 
WHERE FIND_IN_SET(
column1,
(
 SELECT column1 
 FROM B 
 WHERE  id = 21)
);

这里查询SELECT column1 FROM B WHERE id = 21 给出的结果类似于'175587,282329' 但我希望'175587,282329' 会出现我应该使用的最高值。在这种情况下,它将是282329。但是将是任意数量的逗号分隔值。 谢谢

【问题讨论】:

  • 如果您愿意,请考虑遵循以下简单的两步操作: 1. 如果您还没有这样做,请提供适当的 DDL(和/或 sqlfiddle),以便我们可以更轻松地复制问题。 2. 如果您尚未这样做,请提供与步骤 1 中提供的信息相对应的所需结果集。
  • @Strawberry,我只输入了简单的查询形式,我在第二个条件下使用子查询。也许就足够了
  • 为什么不规范化你的数据?
  • @Strawberry,我已经从 API 插入了数据,所以当时不可能
  • 我为你感到抱歉,因为其他人做出了错误的决定。您的问题可以重写为:如何获得逗号分隔列表的最大值。我认为你必须做一些乏味的字符串解析才能做到。

标签: mysql find-in-set


【解决方案1】:

假设 TableA 是这样的

CREATE TABLE A (
    id INT,
    columnA INT
);

以下方法将为您提供多达 100 个分隔值的所需结果(据我所知):

SELECT * FROM A
INNER JOIN (
    SELECT MAX(t.value) as max_value
    FROM (
        SELECT
            id, 
            SUBSTRING_INDEX(SUBSTRING_INDEX(column1, ',', n.n), ',', -1) value
        FROM B CROSS JOIN (
            -- build for up to 100 separated values
            SELECT 
                a.N + b.N * 10 + 1 AS n
            FROM
                (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
               ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
            ORDER BY n
        ) n
        WHERE n <= (1 + LENGTH(column1) - LENGTH(REPLACE(column1, ',', '')))
        AND B.id = 21
    ) t
) t1
ON A.columnA = t1.max_value
;

Demo

说明

最内层的 SELECT 创建一个临时表,其值为 1 到 100:

    SELECT 
        a.N + b.N * 10 + 1 AS n
    FROM
        (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
       ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
    ORDER BY n

此方法是生成此类列表的常用方法,而且速度很快。

嵌套的 SUBSTRING 调用负责获取我们的值,用它进行测试

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(column1, ',', 1), ',', -1) FROM B
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(column1, ',', 2), ',', -1) FROM B

感受一下它的作用。我们限制搜索

1 + LENGTH(column1) - LENGTH(REPLACE(column1, ',', ''))

因为我们的值比值少一个逗号,而且我们也需要最后一个值。 所以声明

SELECT
    id, 
    SUBSTRING_INDEX(SUBSTRING_INDEX(column1, ',', n.n), ',', -1) value
FROM B CROSS JOIN (
    SELECT 
        a.N + b.N * 10 + 1 AS n
    FROM
        (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
       ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
    ORDER BY n
) n
WHERE n <= (1 + LENGTH(column1) - LENGTH(REPLACE(column1, ',', '')))
AND B.id = 21

将返回与 id = 21 对应的 column1 中的值列表。

剩下的就是将此列表的最大值简单连接到 TableA 的相应列。

【讨论】:

    【解决方案2】:

    虽然我不认真提倡将此作为解决方案,但请考虑以下 hack...

     DROP TABLE IF EXISTS my_table;
    
     CREATE TABLE my_table
     (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
     ,string VARCHAR(20) NOT NULL UNIQUE
     );
    
     INSERT INTO my_table(string) VALUES
     ('1,2,3'),
     ('2,3,4'),
     ('3,4,5'),
     ('1,3,5'),
     ('2,4,6');
    
     SELECT * FROM my_table;
     +----+--------+
     | id | string |
     +----+--------+
     |  1 | 1,2,3  |
     |  4 | 1,3,5  |
     |  2 | 2,3,4  |
     |  5 | 2,4,6  |
     |  3 | 3,4,5  |
     +----+--------+
    
     SELECT * FROM ints;
     +---+
     | i |
     +---+
     | 0 |
     | 1 |
     | 2 |
     | 3 |
     | 4 |
     | 5 |
     | 6 |
     | 7 |
     | 8 |
     | 9 |
     +---+
    
     SELECT x.*
          , GROUP_CONCAT(DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(string,',',i+1),',',-1) ORDER BY SUBSTRING_INDEX(SUBSTRING_INDEX(string,',',i),',',-1) DESC) n 
       FROM my_table x
          , ints
      GROUP 
         BY id;
    
     +----+--------+-------+
     | id | string | n     |
     +----+--------+-------+
     |  1 | 1,2,3  | 3,2,1 |
     |  2 | 2,3,4  | 4,3,2 |
     |  3 | 3,4,5  | 5,4,3 |
     |  4 | 1,3,5  | 5,3,1 |
     |  5 | 2,4,6  | 6,4,2 |
     +----+--------+-------+
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-02
      • 2015-12-23
      • 2014-02-19
      • 2017-06-22
      • 1970-01-01
      • 1970-01-01
      • 2013-06-25
      • 1970-01-01
      相关资源
      最近更新 更多