2017-02-06 3 views
1

J'utilise sparq sql. Disons que c'est un instantané de ma grande table:Comment rechercher du texte pour trouver les chaînes de préfixe les plus longues dans SQL?

ups store 
ups store austin 
ups store chicago 
ups store bern 
walmart 
target 

Comment puis-je trouver le plus long préfixe pour les données ci-dessus dans SQL? C'est:

ups store 
walmart 
target 

J'ai déjà un programme Java pour le faire, mais j'ai un gros fichier, maintenant ma question est si cela pouvait être raisonnablement fait dans SQL?

Que diriez-vous du scnenario plus compliqué suivant? (Je peux vivre sans cela, mais bien d'avoir si possible)

ups store austin 
ups store chicago 
ups store bern 
walmart 
target 

et qui retourneront [ups store, walmart, target].

+0

Par préfixe - regardant vos exemples - voulez-vous dire la plus longue chaîne avant le dernier vide entre les mots ? – marcothesane

+0

oui, c'est vrai – user1848018

+0

pourquoi étiez-vous le marquage mysqli et postgresql. Si vous recherchez une réponse SQL, cette balise suffit. – Sebas

Répondre

1

en supposant que vous êtes libre de créer une autre table simplement a une liste d'entiers par ordre croissant de zéro jusqu'à la taille de la plus longue chaîne possible, alors ce qui suit devrait faire le travail en utilisant uniquement ANSI SQL:

SELECT 
    id, 
    SUBSTRING(name, 1, CASE WHEN number = 0 THEN LENGTH(name) ELSE number END) AS prefix 
FROM 
-- Join all places to all possible substring lengths. 
(SELECT * 
    FROM places p 
    CROSS JOIN lengths l) subq 
-- If number is zero then no prefix match was found elsewhere 
-- (from the question it looked like you wanted to include these) 
WHERE (subq.number = 0 OR 
     -- Look for prefix match elsewhere 
     EXISTS (SELECT * FROM places p 
       WHERE SUBSTRING(p.name FROM 1 FOR subq.number) 
        = SUBSTRING(subq.name FROM 1 FOR subq.number) 
       AND p.id <> subq.id)) 
    -- Include as a prefix match if the whole string is being used 
    AND (subq.number = LENGTH(name) 
     -- Don't include trailing spaces in a prefix 
     OR (SUBSTRING(subq.name, subq.number, 1) <> ' ' 
      -- Only include the longest prefix match 
      AND NOT EXISTS (SELECT * FROM places p 
          WHERE SUBSTRING(p.name FROM 1 FOR subq.number + 1) 
           = SUBSTRING(subq.name FROM 1 FOR subq.number + 1) 
          AND p.id <> subq.id))) 
ORDER BY id; 

démonstration en direct:http://rextester.com/XPNRP24390

La deuxième aspect est que si nous avons (ups store austin, ups magasin Chicago). pouvons-nous utiliser SQL pour en extraire le 'ups store'?

Cela devrait être tout simplement un cas d'utilisation SUBSTRING de manière similaire ci-dessus, par exemple:

SELECT SUBSTRING(name, 
       LENGTH('ups store ') + 1, 
       LENGTH(name) - LENGTH('ups store ')) 
FROM places 
WHERE SUBSTRING(name, 
       1, 
       LENGTH('ups store ')) = 'ups store '; 
+0

Merci, n'ont pas accès à un système. vais tester très très bientôt – user1848018

+0

Essayé votre code, sur étincelle SQL, retourné juste "ups magasin", n'a pas listé [cible, walmart], mais quand je l'ai couru dans votre site en ligne, il a renvoyé [cible, walmart]. Ce n'est pas un gros problème cependant, j'étais juste surpris – user1848018

+0

Hmmm c'est étrange, ces valeurs devraient être retournées de la condition 'subq.number = 0 OR ...' puisque dans ce cas aucun préfixe n'a été trouvé ailleurs. –

0

Supposant votre nom de colonne est « mycolumn », et votre grande table est « mytable », et un seul espace est votre séparateur de champ:

Dans PostgreSQL, vous pouvez faire quelque chose d'aussi simple que cela:

select 
    mycolumn 
from 
    mytable 
order by 
    length(split_part(mycolumn, ' ', 1)) desc 
limit 
    1 

Si vous avez exécuté cette requête souvent, j'essaierais un indice fonctionnel commandé sur la table comme ceci:

create prefix_index on mytable (length(split_part(mycolumn, ' ', 1)) desc)