简体   繁体   English

从同一个表中过滤逗号分隔值

[英]Filter comma separated values from same table

逗号分隔的值不在id列中

Can anybody help me to get the sub_cat(csv) values which are not in id column from same table. 任何人都可以帮助我从同一个表中获取不在id列中的sub_cat(csv)值。

(sub_cat) comma separated values are the ids of same table, i need to get the values which are not in id column. (sub_cat)逗号分隔值是同一个表的id,我需要获取不在id列中的值。 Like 2,3,7 are present in id column whereas 20,24 are not. 像id列中的2,3,7一样,而20,24则不存在。 I need to get 20,24 only. 我只需要20,24。

As I have elaborated in this post, I recommend not storing data in CSV format. 正如我在这篇文章中详细阐述的那样,我建议不要以CSV格式存储数据。 This gives trouble accessing and updating it. 这使得访问和更新它变得困难。

I am not sure about this, but you might be able to simply use: 我不确定这一点,但您可以简单地使用:

SELECT sub_cat FROM table_name WHERE id NOT IN (
    SELECT sub_cat FROM table_name
)

However, I always prefer to store only one ID per row. 但是,我总是喜欢每行只存储一个ID。

To do this purely in MySQL required writing a stored procedure; 纯粹在MySQL中这样做需要编写存储过程; you'll need to change the database name test to the actual name of your database. 您需要将数据库名称test更改为数据库的实际名称。 It would have been a whole lot easier to do it with PHP - but where's the fun in that? 用PHP做这件事会好得多 - 但那里的乐趣在哪里?

DELIMITER //

CREATE PROCEDURE test.check_subcats(
    IN s_delimiter VARCHAR(30)
    )

    DETERMINISTIC
    READS SQL DATA

    BEGIN
        DECLARE s_csv TEXT;
        DECLARE i_subcat_index INT(10) unsigned DEFAULT 1;
        DECLARE i_subcat_count INT(10) unsigned;
        DECLARE l_category_done INT(10) DEFAULT FALSE;
        DECLARE c_category CURSOR FOR SELECT category.sub_cat FROM category;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET l_category_done = TRUE;

        -- create a temporary table to hold every csv value
        CREATE TEMPORARY TABLE IF NOT EXISTS tmp_csv( cvalue VARCHAR(10) NOT NULL );

        OPEN c_category;
        l_category: LOOP
            FETCH c_category INTO s_csv;

            IF l_category_done THEN
                LEAVE l_category;
            ELSE
                -- determine the number of sub-categories
                SELECT (LENGTH(s_csv) - LENGTH(REPLACE(s_csv, s_delimiter, ''))) + 1 INTO i_subcat_count;

                -- loop to store all csv values
                WHILE i_subcat_index <= i_subcat_count DO 
                    INSERT INTO tmp_csv ( cvalue ) (
                    SELECT REPLACE(SUBSTRING(
                            SUBSTRING_INDEX(s_csv, s_delimiter, i_subcat_index),
                            LENGTH(SUBSTRING_INDEX(s_csv, s_delimiter, i_subcat_index - 1)) + 1
                        ), s_delimiter, '')
                    );

                    SET i_subcat_index = i_subcat_index + 1;
                END WHILE;
            END IF;

            SET i_subcat_index = 1;
        END LOOP;       
        CLOSE c_category;

        SELECT DISTINCT tmp_csv.cvalue FROM tmp_csv WHERE tmp_csv.cvalue NOT IN ( SELECT category.id FROM category );
        DROP TEMPORARY TABLE IF EXISTS tmp_csv;
    END //

DELIMITER ;

I'm not 100% certain as to how robust it is but it was working with your data on my dev box. 我不是百分之百确定它有多强大,但它正在我的开发盒上使用你的数据。

You specify the delimiter for your CSV data when you call the procedure thus: 您在调用过程时指定CSV数据的分隔符:

CALL `check_subcats`(',');

Essentially this loops through the category table to read sub_cat . 本质上,这会循环通过category表来读取sub_cat It then splits the sub_cat value into chunks using the delimiter provided (much like PHPs explode() function) and writes every one of those values to a temporary table. 然后使用提供的分隔符将sub_cat值拆分为块(非常类似于PHPs explode()函数),并将每个值写入临时表。

This then gives you a temporary table holding all your CSV data in individual bits and it's then a simple matter of selecting everything from that data that's NOT IN the category.id list. 然后,这会为您提供一个临时表,将所有CSV数据保存在各个位中,然后从一个NOT IN category.id列表中的数据中选择所有内容就可以了。

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

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