J'ai une table avec des variables / colonnes mappées, par exemple:
SELECT * FROM test WHERE ele = '123' (dim1 = 'DM1' OR dim1 = '*') AND (dim2 = 'DM2' OR dim2 = '*') AND (dim3 = 'DM3' OR dim3 = '*');
Je veux trouver la première correspondance avec n'importe quelle colonne qui pourrait renvoyer la correspondance requise à partir de la colonne ou du caractère générique à la place.
+------+------+------+------+ | ele | dim1 | dim2 | dim3 | +------+------+------+------+ | 123 | * | * | * | | 123 | DM1 | * | * | | abc | * | DM2 | * | +------+------+------+------+ CREATE TABLE `test` ( `ele` varchar(36) NOT NULL, `dim1` varchar(36) NOT NULL, `dim2` varchar(36) NOT NULL, `dim3` varchar(36) NOT NULL, UNIQUE KEY `test_dim1_dim2_dim3_uindex` (`ele`, `dim1`,`dim2`,`dim3`) );
Il se produit que cela renvoie les deux colonnes (trouvé un et le caractère générique correspondant, bien sûr).
Existe-t-il un moyen de trouver une correspondance ou un caractère générique en cas d'échec? p >
3 Réponses :
Faites-le comme deux requêtes distinctes, que vous combinez avec UNION
. Donnez-leur à chacun une colonne de classement et utilisez-la pour préférer la correspondance réelle au lieu du caractère générique.
SELECT * FROM ( SELECT 1 AS o, test.* FROM test WHERE dim1 = 'DM1' OR dim2 = 'DM2' OR dim3 = 'DM3' LIMIT 1 UNION SELECT 2 AS o, test.* FROM test WHERE dim1 = '*' AND dim2 = '*' AND dim3 = '*' LIMIT 1 ) AS x ORDER BY o LIMIT 1
Cela effectue une recherche complète dans 3 requêtes dérivées. Cela ne semble pas être le moyen le plus performant, mais merci quand même.
Vous pouvez mettre LIMIT 1
dans les sous-requêtes pour que l'union finale soit minuscule. Il devrait probablement y avoir un ordre dans les sous-requêtes également, mais il n'y a rien dans votre question initiale qui suggère comment classer les deux types de résultats.
Pas une réponse; trop long pour un commentaire ...
Un environnement normalisé pourrait ressembler davantage à ceci:
entity dim val 1 1 * 1 2 * 1 3 * 2 1 DM1 2 2 * 2 3 *
Quoi de neuf dans cet environnement? J'utilise DM1
, DM2
comme exemple, mais la colonne a en fait des valeurs UUID
et UNIQUE INDEX
sur les combinaisons également . Quoi qu'il en soit, la question a été modifiée pour être claire.
Une façon de faire serait de compter le nombre de correspondances génériques pour chaque ligne (en tirant parti du fait que dans un contexte numérique MySQL traite un booléen comme 1 ou 0), puis triez par ce nombre croissant, a LIMIT 1
pour renvoyer uniquement la ligne avec le moins de correspondances génériques, par exemple
ele dim1 dim2 dim3 123 DM1 * *
Sortie:
SELECT * FROM test WHERE ele = 123 AND (dim1 = 'DM1' OR dim1 = '*') AND (dim2 = 'DM2' OR dim2 = '*') AND (dim3 = 'DM3' OR dim3 = '*') ORDER BY (dim1 = '*') + (dim2 = '*') + (dim3 = '*') ASC LIMIT 1
@fiskolin J'ai modifié ma réponse en fonction des modifications que vous avez apportées à votre question. Avez-vous besoin d'autre chose?
Vous avez d'abord besoin d'un membre de commande pour définir le premier et le suivant. Ensuite,
ORDER BY order_member LIMIT1
peut vous aider.Ce type de problème est symptomatique d'une mauvaise conception. Pouvez-vous modifier votre schéma?
@ Fraise ouais, je peux le modifier. Toute suggestion?
L'une de ces réponses a-t-elle résolu votre problème? Sinon, pourriez-vous fournir plus d'informations pour y répondre? Sinon, pensez à marquer la réponse qui a le mieux résolu votre problème. Voir stackoverflow.com/help/someone-answers