SQLite:如何限制 GROUP_CONCAT 的子查询

问题描述 投票:0回答:1

我有一个提供 GROUP_CONCAT 的子查询。除了 LIMIT 之外,一切都很好,它没有达到我想要的效果。

这是代码:

CREATE TABLE IF NOT EXISTS Animal (
    id  TEXT    PRIMARY KEY,
    diet    TEXT
    );
INSERT INTO Animal VALUES ('monkey',    'herbivore');
INSERT INTO Animal VALUES ('goat',  'herbivore');
INSERT INTO Animal VALUES ('cat',   'carnivore');
INSERT INTO Animal VALUES ('dog',   'omnivore');
INSERT INTO Animal VALUES ('human', 'omnivore');

CREATE TABLE IF NOT EXISTS Domicile (
    id  TEXT    PRIMARY KEY REFERENCES Animal,
    home    TEXT
    );

INSERT INTO Domicile VALUES ('monkey',  'jungle');
INSERT INTO Domicile VALUES ('goat',    'farmyard');
INSERT INTO Domicile VALUES ('cat', 'house');
INSERT INTO Domicile VALUES ('dog', 'garden');
INSERT INTO Domicile VALUES ('human',   'house');

CREATE TABLE IF NOT EXISTS Food (
    name    TEXT    PRIMARY KEY
    );

INSERT INTO Food VALUES ('fruit');
INSERT INTO Food VALUES ('meat');
INSERT INTO Food VALUES ('fish');
INSERT INTO Food VALUES ('bread');
INSERT INTO Food VALUES ('sausages');

CREATE TABLE IF NOT EXISTS Eats (
    id  TEXT    REFERENCES Animal,
    name    TEXT    REFERENCES Food
    );

INSERT INTO Eats VALUES ('monkey',  'fruit');
INSERT INTO Eats VALUES ('monkey',  'bread');
INSERT INTO Eats VALUES ('goat',    'fruit');
INSERT INTO Eats VALUES ('cat',     'meat');
INSERT INTO Eats VALUES ('cat',     'sausages');
INSERT INTO Eats VALUES ('dog',     'meat');
INSERT INTO Eats VALUES ('dog',     'bread');
INSERT INTO Eats VALUES ('dog',     'sausages');
INSERT INTO Eats VALUES ('human',   'fruit');
INSERT INTO Eats VALUES ('human',   'meat');
INSERT INTO Eats VALUES ('human',   'fish');
INSERT INTO Eats VALUES ('human',   'bread');
INSERT INTO Eats VALUES ('human',   'sausages');

.mode column

SELECT 'TEST 4: JOIN Eats using a subquery to order the names.';
SELECT      Animal.id,
        Animal.diet,
        GROUP_CONCAT (Eats.name) as names,
        Domicile.home
FROM        Animal
        INNER JOIN Domicile USING (id)
        INNER JOIN (
            SELECT * FROM Eats
            ORDER BY name
            ) as Eats USING (id)
GROUP BY    Animal.id
ORDER BY    Animal.id
;
SELECT 'TEST 4 result: names in order, but not limited to 3.';

SELECT 'TEST 5: LIMIT Eats subquery to 3.';
SELECT      Animal.id,
        Animal.diet,
        GROUP_CONCAT (Eats.name) as names,
        Domicile.home
FROM        Animal
        INNER JOIN Domicile USING (id)
        INNER JOIN (
            SELECT * FROM Eats
            ORDER BY name
            LIMIT 3
            ) as Eats USING (id)
GROUP BY    Animal.id
ORDER BY    Animal.id
;
SELECT 'TEST 5 result: LIMIT has applied to wrong SELECT?.';

我想要的是这样的输出:

id      diet       names                home
------  ---------  -------------------  --------
cat     carnivore  meat,sausages        house
dog     omnivore   bread,meat,sausages  garden
goat    herbivore  fruit                farmyard
human   omnivore   bread,fish,fruit     house
monkey  herbivore  bread,fruit          jungle

备注:

  1. 按“id”排序的行。
  2. 并非所有可能的组合都存在于 Eats 中。 (例如山羊只吃水果)。
  3. 'names' 列按字母顺序排列,最多包含 3 个元素 (否则“人类”将是面包、鱼、水果、肉、香肠)。

我从两次测试中得到的是这样的:

'TEST 4: JOIN Eats using a subquery to order the names.'
--------------------------------------------------------
TEST 4: JOIN Eats using a subquery to order the names.  
id      diet       names                           home    
------  ---------  ------------------------------  --------
cat     carnivore  meat,sausages                   house   
dog     omnivore   bread,meat,sausages             garden  
goat    herbivore  fruit                           farmyard
human   omnivore   bread,fish,fruit,meat,sausages  house   
monkey  herbivore  bread,fruit                     jungle  
'TEST 4 result: names in order, but not limited to 3.'
------------------------------------------------------
TEST 4 result: names in order, but not limited to 3.  
'TEST 5: LIMIT Eats subquery to 3.'
-----------------------------------
TEST 5: LIMIT Eats subquery to 3.  
id      diet       names  home  
------  ---------  -----  ------
dog     omnivore   bread  garden
human   omnivore   bread  house 
monkey  herbivore  bread  jungle
'TEST 5 result: LIMIT has applied to wrong SELECT?.'
----------------------------------------------------
TEST 5 result: LIMIT has applied to wrong SELECT?.  

测试 4 和 5 的源之间的唯一区别是测试 5 子查询中的 LIMIT。

有没有办法将名称限制为 3 个元素? (我希望该限制能够轻松更改。)

sqlite subquery limit
1个回答
0
投票

我相信以下是解决方案:-

WITH
    cte1 AS (
        SELECT 
            animal.*,
            domicile.home,
            eats.name 
        FROM animal 
        JOIN eats ON eats.id = animal.id 
        JOIN domicile ON domicile.id = animal.id
        ORDER BY animal.id,eats.id
        ),
    cte2 AS (
        SELECT *, (
            SELECT count(*) FROM cte1 AS cte1_c 
            WHERE cte1_c.name <= cte1.name AND cte1_c.id = cte1.id ORDER BY id,name
        ) AS c 
        FROM cte1
    )
SELECT id,diet,group_concat(name) AS names,home FROM cte2 WHERE c <= 3 GROUP BY id;

结果是:-

通过更改最后一个 WHERE 子句中的数字,可以轻松更改多少个 names

WHERE c <= 3

© www.soinside.com 2019 - 2024. All rights reserved.