Problem mit subquery, die eine Liste in Form von longtext zurückliefert

fabmeyer

Neuer Benutzer
Beiträge
4
Hallo. Ich habe die folgende query:

SQL:
SET @portfolio_id = 1;
SELECT configure_country.name
FROM configure_country
WHERE configure_country.id
IN (
    SELECT filters_portfoliofilter.values
    FROM filters_portfoliofilter
    WHERE filter_id = 1
    AND portfolio_id = @portfolio_id;
);

die nicht funktioniert.

Wenn ich die folgende query laufen lasse:

SQL:
SET @portfolio_id = 1;
SELECT filters_portfoliofilter.values
FROM filters_portfoliofilter
WHERE filter_id = 1
AND portfolio_id = @portfolio_id;

Dann kommt das folgende zurück:
values
3, 4, 7

eine Tabelle, die Spalte values hat jedoch den Typ longtext...

irgendwie muss ich die einzelnen, kommagetrennten Werte in integers umwandeln?

Setze ich in die IN Klausel nämlich eine Liste (z.B. "1, 2, 3") ein, dann funktioniert es.

Vielen Dank!
 
Werbung:
Deine Annahme ist korrekt, aus dem String muss eine Werte-Liste werden, sonst geht es nicht. Wie das genau funktionieren kann ist sehr stark vom DBMS abhängig, ich habe da keine Erfahrung bei MariaDB oder MySQL, ich könnte dir die MSSQL Lösung aufschreiben :). Vielleicht hilft das hier weiter:
 
Versuch mal das. Sollte gehen, habs aber nicht getestet, da ich gerade keine DB frei habe.



Code:
SET @portfolio_id = 1;
SELEC filters_portfoliofilter.values INTO @ids
FROM filters_portfoliofilter
WHERE filter_id = 1
AND portfolio_id = @portfolio_id;
SELECT configure_country.name
FROM configure_country
WHERE FIND_IN_SET(configure_country.id.@ids) >0;

oder

Code:
SET @portfolio_id = 1;
SELECT configure_country.name
FROM configure_country
CROSS JOIN ( SELECT INTO filters_portfoliofilter.values
  FROM filters_portfoliofilter
  WHERE filter_id = 1
  AND portfolio_id = @portfolio_id) AS fp
WHERE FIND_IN_SET(configure_country.id, fp.values) >0;

Schreib mal obs geht, sonst schau ich später mal
 
Versuch mal das. Sollte gehen, habs aber nicht getestet, da ich gerade keine DB frei habe.



Code:
SET @portfolio_id = 1;
SELEC filters_portfoliofilter.values INTO @ids
FROM filters_portfoliofilter
WHERE filter_id = 1
AND portfolio_id = @portfolio_id;
SELECT configure_country.name
FROM configure_country
WHERE FIND_IN_SET(configure_country.id.@ids) >0;

oder

Code:
SET @portfolio_id = 1;
SELECT configure_country.name
FROM configure_country
CROSS JOIN ( SELECT INTO filters_portfoliofilter.values
  FROM filters_portfoliofilter
  WHERE filter_id = 1
  AND portfolio_id = @portfolio_id) AS fp
WHERE FIND_IN_SET(configure_country.id, fp.values) >0;

Schreib mal obs geht, sonst schau ich später mal

Hallo Bernd und vielen vielen Dank für die Antwort. Leider bekomme ich bei beiden queries ein parse error zurück. Auch der online Validator gibt ein parse error zurück. Ich bin echt Anfänger in SQL und bin um jede Hilfe froh 🙏
 
Leider bekomme ich bei beiden queries ein parse error zurück.
Code:
postgres=# create table demo as select * from generate_series(1,10) s;
SELECT 10
postgres=# select * from demo;
 s  
----
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
(10 rows)

postgres=# create table liste (id int, filter text);
CREATE TABLE
postgres=# insert into liste values (1, '3, 4, 7');
INSERT 0 1
postgres=# select * from liste ;
 id | filter  
----+---------
  1 | 3, 4, 7
(1 row)
postgres=# select * from demo where  s in (select regexp_split_to_table(filter, ', ')::int from liste where id = 1);
 s 
---
 3
 4
 7
(3 rows)

postgres=#

Beachte #3
 
Code:
postgres=# create table demo as select * from generate_series(1,10) s;
SELECT 10
postgres=# select * from demo;
 s 
----
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
(10 rows)

postgres=# create table liste (id int, filter text);
CREATE TABLE
postgres=# insert into liste values (1, '3, 4, 7');
INSERT 0 1
postgres=# select * from liste ;
 id | filter 
----+---------
  1 | 3, 4, 7
(1 row)
postgres=# select * from demo where  s in (select regexp_split_to_table(filter, ', ')::int from liste where id = 1);
 s
---
 3
 4
 7
(3 rows)

postgres=#

Beachte #3
Danke für die Antwort. So wie ich das verstehe funktioniert die query aber nur für Postgres? Wie würde das für Mysql aussehen?
Ich hab jetzt diesen code hier:

SQL:
SET @portfolio_id = 1;
SELECT configure_country.name
FROM configure_country
WHERE configure_country.id
IN (
SELECT regexp_split_to_table(filters_portfoliofilter.values, ', ')::int
FROM filters_portfoliofilter
WHERE filters_portfoliofilter.filter_id = 1
AND filters_portfoliofilter.portfolio_id = @portfolio_id
);
 
regexp_split_to_table
das gibt es glaub ich nicht in MySQL

Und es ist vielleicht eine ziemliche Frickelei, das mit SQL Bordmitteln von MySQL zu verarbeiten.
Da Du bei diesem Datenmodel String Operationen verwenden musst und es nicht zerlegen kannst, wäre ggf. eine andere Modellierung ratsam.

Es gäbe theoretisch die Möglichkeit mit INSTR zu arbeiten (Zumindest gibt es tapfere "Lösungen" damit). Aber da kommt man vom Regen in die Traufe, wenn man exakte ID finden will, tatsächlich aber Ausschnitte anderer ID findet:
instr('3, 4, 7', '4')
geht super
instr('3,7, 44', '4')
geht leider auch super, ist aber hier vermutlich nicht gewollt.

Mir fällt keine mySQL Funktion ein dafür, ich nutze es aber auch nie. Es gibt hier mysql Experten, die vielleicht eine Lösung kennen.
 
Aber wahrscheinlich würde als Stringoperation FIND_IN_SET(string, string_list) helfen.
Wäre jedenfalls besser als das bescheuerte Instr-Verfahren.
 
Ich habe auch kein MySQL hier laufen aber hier eine vielversprechende Lösung für MySQL 8:
Das muss man natürlich anpassen und wenn ich das richtig verstehe sind da noch Leerschritte hinter dem Trennzeichen aber wenn man dem Ansatz erstmal folgt bekommt man aus 3, 4, 7 eine vernünftige Tabelle die man joinen kann.
 
Werbung:
Hallo zusammen und vielen, vielen Dank! Ich bin nun zur weniger eleganten Lösung übergegangen dieses Problem in Python zu lösen (die SQL scripts werden innerhalb einer Python Applikation ausgeführt). Und ja, das Datenmodell könnte sicher besser sein. LG
 
Zurück
Oben