簡體   English   中英

如何將逗號分隔的字符串轉換為SET以在MySQL的另一個查詢中使用?

[英]How to convert a comma separated string into a SET to use in another query in MySQL?

讓我們假設我們有兩個MySQL表。

id  |  master  |  meta
1   |  78564   |  2,3,4
2   |  89567   |  1,3
3   |  45782   |  2,1,4

和元數據

id  |  buyer_id  |  platform
1   |  25        |  mobile
2   |  35        |  web
3   |  25        |  web
4   |  17        |  api

輸入主名稱時,我需要獲取buyer_id和平台的數組。 主列是唯一索引,元數據的id也是唯一索引。 我想要類似的東西:

SELECT buyer_id, platform FROM metadata WHERE id IN (SELECT meta FROM 
master WHERE master = '89567')

上面的查詢不起作用,因為子查詢返回一個字符串。 我需要某種方式將該子查詢結果轉換為SET。 我目前正在使用PHP來做到這一點。

<?php $sql="SELECT meta FROM master WHERE master = '89567'";
$result = $connection->query($sql);
$result = $result->fetch_assoc();
$meta = $result['meta'];
$sql="SELECT buyer_id, platform FROM metadata WHERE id IN (".$meta.")";
$result = $connection->query($sql);?>

我正在獲得所需的結果,但我想對其進行優化。 我希望使用子查詢或JOIN在單個查詢中完成全部操作。

背景故事 :我首先只使用一個表來存儲所有數據。 它也被序列化了。 我沒有使用任何索引,執行時間為0.290010929。
然后,我將非唯一索引用於主表的主列。 我仍然只使用一個表,執行時間為0.0186100006。
然后,我將表分成兩部分,每個表都有一個唯一索引,如上所述。 我正在使用上面的PHP代碼,執行時間為0.0011548995。

我敢肯定,如果您可以回答我的問題,我可以將執行時間減少到0.0005。 我這樣做是針對流量非常高的RESTful API。 我想將其最佳化。 請幫我。

更新 :感謝@RiggsFolly。
我改變了桌子的結構。

id  |  master(unique index)
1   |  78564
2   |  89567
3   |  45782

和元數據

id  |  master_id  |  buyer_id  |  platform
1   |     2       |  25        |  mobile
2   |     3       |  25        |  mobile
3   |     1       |  35        |  web
4   |     3       |  35        |  web
5   |     1       |  25        |  web
6   |     2       |  25        |  web
7   |     1       |  17        |  api
8   |     3       |  17        |  api

master_id是非唯一索引。
現在,我的查詢是

SELECT buyer_id, platform FROM metadata WHERE master_id = (SELECT id FROM master WHERE 
master = '89567')

執行時間為0.00079298019。
我認為即使將字符串轉換為SET,執行時間也不會減少。 但是,我仍然想知道我的問題的答案。

使用觸發器保留一個預先計算的表。

create table master_metadata(
    masterid bigint(10),
    metaid   bigint(10)
);

那么,您的查詢應為:

SELECT buyer_id, platform
FROM metadata
WHERE id IN(
        SELECT metaid
        FROM master_metadata
        WHERE masterid = '89567'
    );

下面是將保留此表的代碼。

drop procedure if exists sp_tr_master_insert_update;
drop trigger if exists tr_master_insert;
drop trigger if exists tr_master_update;

delimiter //

create
    definer=root@localhost
    procedure sp_tr_master_insert_update(
            in _masterid bigint(10)
        )
modifies sql data
reads sql data
begin
    declare metaids varchar(255);
    --
    declare commapos int;
    declare metaid   varchar(255);

    -- -------------------------------------------------------------------------

    delete from master_metadata
    where masterid = _masterid;

    -- -------------------------------------------------------------------------

    set metaids =(
            select meta
            from master
            where master = _masterid
        );

    if coalesce(metaids, '') <> '' then
        _split: LOOP
            set commapos = locate(',', metaids);

            if commapos = 0 then
                insert into master_metadata
                values(_masterid, metaids);

                leave _split;
            else
                set metaid = left(metaids, commapos - 1);
                set metaids = right(metaids, length(metaids) - commapos);

                insert into master_metadata
                values(_masterid, metaid);                
            end if;
        END LOOP _split;
    end if;
end //

CREATE DEFINER=root@localhost TRIGGER tr_master_insert
AFTER insert ON master
FOR EACH ROW
BEGIN
    CALL sp_tr_master_insert_update(NEW.master);
END//

CREATE DEFINER=root@localhost TRIGGER tr_master_update
AFTER update ON master
FOR EACH ROW
BEGIN
    CALL sp_tr_master_insert_update(NEW.master);
END//


delimiter ;

索引創建和其他性能調整取決於您。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM