2009-10-05 7 views
6

J'ai en quelque sorte besoin de cette fonctionnalité, mais MySQL ne la supporte pas pour le moment. J'utilise GROUP_CONCAT(CONCAT(...)) pour générer un contenu semblable à xml.Comment pirater MySQL GROUP_CONCAT pour récupérer un nombre limité de lignes?

Mais quand la taille dépasse la limite, le xml est juste cassé!

Donc, je dois le faire en quelque sorte que récupérer 5 lignes!

+0

augmentation valeur group_concat_max_len dans my.cnf – Omesh

+1

peut être vous pouvez obtenir votre réponse ici http://stackoverflow.com/questions/3378324/limit-ignored-in-query-with-group-concat http://stackoverflow.com/questions/23608464/group-concat-with-limit –

Répondre

2

Utilisez une table/sous-requête temporaire pour limiter les résultats? Sans voir votre requête, il sera difficile de donner des conseils solides pour cette route.

Toutefois, vous pouvez trouver le paramètre group_concat_max_len plus utile. Il contrôle la longueur maximale d'une opération GROUP_CONCAT, en longueur de chaîne. Le soulever pour éviter les GROUP_CONCAT s, quand vous ne pouvez pas se permettre de limiter les résultats.

2

Pas vraiment une réponse à votre question, mais un arbitre pour d'autres personnes qui voudraient également utiliser une clause LIMIT dans GROUP_CONCAT():

A feature-request a été déposée il y a longtemps aux développeurs MySql. Pas encore mis en œuvre :-(

4

Un exemple pour la réponse Charles:

de base:

SELECT GROUP_CONCAT(field) FROM (SELECT field FROM table LIMIT 200) 

étendu:

CAST peut être utile si le résultat est tronqué par le tampon:

SELECT CAST(GROUP_CONCAT(field) AS CHAR(2048)) FROM (SELECT field FROM table LIMIT 200) 
+0

Oui, cela fonctionnera. Mais il faudra une construction plus complexe pour une requête avec 'GROUP BY'. –

+0

J'ai une erreur pour "Chaque table dérivée doit avoir son propre alias" lors de l'utilisation de la première requête. Pour corriger cela, je l'ai changé à "SELECT GROUP_CONCAT (champ) FROM (champ SELECT FROM table LIMIT 200) AS alias" Merci pour la réponse. – Henry

15

J'ai travaillé autour de cela en utilisant SUBSTRING_INDEX

Par exemple:

SELECT SUBSTRING_INDEX(GROUP_CONCAT(Field1 SEPARATOR ','), ',', [# of elements to return]) 
FROM Table1; 
+0

Il renvoie blob, mais celui-ci fonctionne. –

0

Pour les cas où vous ne pouvez pas utiliser une table temporaire, la meilleure façon que je connaisse est de sélectionner un séparateur obscur, puis tronquer à partir de la première instance dudit caractère. Cet exemple utilise le caractère NUL.

select substring_index(group_concat(field separator '\0'), '\0', 5) from table;

field est le nom du champ, 5 est le nombre de résultats. L'inconvénient est que si votre première ligne contient ce caractère, ce sera un résultat partiel.

Une solution de contournement consiste à remplacer '\0' par une chaîne aléatoire plus longue. Il est bon de savoir que field peut être remplacé pour inclure plus d'informations en utilisant concat. Gardez à l'esprit les group_concat_max_len par défaut 1024 caractères, donc vous devriez envisager de changer cela globalement ou dans votre application si vous voulez plus que cela.

0

Vous pouvez simuler la partitionné row_number en utilisant les variables utilisateur, puis limiter les lignes et appliquer group_concat:

Considérez le tableau suivant:

create table your_table (
    id int primary key autoincrement, 
    category int, 
    value int 
); 

et des données:

insert into your_table (category, value) 
values 
(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), 
(2, 6), (2, 7), (2, 8), (2, 9), (2, 10), 
(3, 11), (3, 12), (3, 13), (3, 14), (3, 15); 

Et nous voulons est le top 3 (dans l'ordre du dernier identifiant) valeur par catégorie concaténée:

select category, 
    group_concat(value order by id desc) as value_con 
from (
    select t.*, 
     @rn := if(@category = category, @rn + 1, if(@category := category,1, 1)) as seqnum 
    from your_table t 
    cross join (select @category := null, @rn := 0) x 
    order by t.category, t.id desc 
    ) t 
where seqnum <= 3 
group by category; 

Sortie:

category value_con 
1   5,4,3 
2   10,9,8 
3   15,14,13 

Voici une demo de cela.

Questions connexes