Oplossing voor de fout ‘subquery retourneert meer dan 1 rij’

Ik heb een query die meerdere rijen retourneert, en een andere query waarin ik criteria wil instellen als een van de waarden uit die meerdere rijen , dus eigenlijk wil ik dat de subquery er ongeveer zo uitziet:

select * 
from table
where id= (multiple row query);

Waar multiple row querymeerdere rijen retourneert. Dus als de waarden van die rijen 1,2,3 zijn, dan wil ik id instellen op 1 of 2 of 3.


Antwoord 1, autoriteit 100%

=kan worden gebruikt wanneer de subquery slechts 1 waarde retourneert.

Als een subquery meer dan 1 waarde retourneert, moet u INgebruiken:

select * 
from table
where id IN (multiple row query);

Bijvoorbeeld:

SELECT *
FROM Students
WHERE Marks = (SELECT MAX(Marks) FROM Students)   --Subquery returns only 1 value
SELECT *
FROM Students
WHERE Marks IN 
      (SELECT Marks 
       FROM Students 
       ORDER BY Marks DESC
       LIMIT 10)                       --Subquery returns 10 values

Antwoord 2, autoriteit 9%

U kunt in()gebruiken:

select * 
from table
where id in (multiple row query)

of gebruik een join:

select distinct t.* 
from source_of_id_table s
join table t on t.id = s.t_id
where <conditions for source_of_id_table>

De join is nooit een slechtere keuze voor prestaties en kan, afhankelijk van de exacte situatie en de database die u gebruikt, veel betere prestaties leveren.


Antwoord 3, autoriteit 2%

Gebruik MAXin uw SELECT-zoekopdracht om één waarde te retourneren… VOORBEELD

INSERT INTO school_year_studentid (student_id,syr_id) VALUES
((SELECT MAX(student_id) FROM student), (SELECT MAX(syr_id) FROM school_year))

in plaats van

INSERT INTO school_year_studentid (student_id,syr_id) VALUES
((SELECT (student_id) FROM student), (SELECT (syr_id) FROM school_year))

probeer het zonder MAX, het geeft meer dan één waarde terug


Antwoord 4

Als je de foutmelding krijgt ‘subquery retourneert meer dan 1 rij’, vertelt de database je eigenlijk dat er een onoplosbare kringverwijzing is. Het is een beetje alsof je een spreadsheet gebruikt en cel A1 = B1 zegt en dan zegt B1 = A1. Deze fout wordt meestal geassocieerd met een scenario waarin een dubbel geneste subquery nodig is. Ik raad je aan iets op te zoeken dat een ‘kruistabelquery‘ wordt genoemd. Dit is het type zoekopdracht dat je normaal gesproken nodig hebt om dit probleem op te lossen. Het is in feite een outer join (links of rechts) die is genest in een subquery of omgekeerd. Je kunt dit probleem ook oplossen met een dubbele join (ook beschouwd als een type kruistabelquery), zoals hieronder:

CREATE DEFINER=`root`@`localhost` PROCEDURE `SP_GET_VEHICLES_IN`(
    IN P_email VARCHAR(150),
    IN P_credentials VARCHAR(150)
)
BEGIN
    DECLARE V_user_id INT(11);
    SET V_user_id = (SELECT user_id FROM users WHERE email = P_email AND credentials = P_credentials LIMIT 1);
    SELECT vehicles_in.vehicle_id, vehicles_in.make_id, vehicles_in.model_id, vehicles_in.model_year,
    vehicles_in.registration, vehicles_in.date_taken, make.make_label, model.model_label
    FROM make
    LEFT OUTER JOIN vehicles_in ON vehicles_in.make_id = make.make_id
    LEFT OUTER JOIN model ON model.make_id = make.make_id AND vehicles_in.model_id = model.model_id
    WHERE vehicles_in.user_id = V_user_id;
END

Merk in de bovenstaande code op dat er drie tabellen zijn in de SELECT-clausule en deze drie tabellen verschijnen na de FROM-clausule en na de twee LEFT OUTER JOIN-clausules, deze drie tabellen moeten verschillend zijn tussen de FROM en LEFT OUTER JOIN clausules syntactisch correct zijn.

Het is opmerkelijk dat dit een zeer belangrijke constructie is om te kennen als ontwikkelaar, vooral als je periodieke rapportquery’s schrijft en het is waarschijnlijk de belangrijkste vaardigheid voor complexe kruisverwijzingen, dus alle ontwikkelaars zouden deze constructies moeten bestuderen (kruistabelen double join).

Een ander ding waar ik voor moet waarschuwen is: als u een kruistabel gaat gebruiken als onderdeel van een werkend systeem en niet alleen als een periodiek rapport, moet u het aantal records controleren en de deelnamevoorwaarden opnieuw configureren tot het minimum aantal records worden geretourneerd, anders kunnen grote tabellen en kruistabellen uw server tot stilstand brengen.
Ik hoop dat dit helpt.


Antwoord 5

Mijn antwoord toevoegen, omdat het het idee uitwerkt dat je meerdere kolommen kunt SELECTEREN uit de tabel waaruit je subquery’s uitvoert.

Hier had ik de meest recente cast nodig en de bijbehorende informatie.

Ik heb eerst geprobeerd om de max(votedate) samen met de stem, itemid, userid etc. te SELECTEREN, maar terwijl de query de max voteate zou retourneren, zou het ook een willekeurige rij voor de andere informatie retourneren. Moeilijk te zien tussen een stel enen en nullen.

Dit werkte goed:

$query = "  
    SELECT t1.itemid, t1.itemtext, t2.vote, t2.votedate, t2.userid 
    FROM
        (
        SELECT itemid, itemtext FROM oc_item ) t1
    LEFT JOIN 
        (
        SELECT vote, votedate, itemid,userid FROM oc_votes
        WHERE votedate IN 
        (select max(votedate) FROM oc_votes group by itemid)
        AND userid=:userid) t2
    ON (t1.itemid = t2.itemid)
    order by itemid ASC
";

De subquery in de WHERE-clausule WAAR gestemd IN
(selecteer max(votedate) FROM oc_votes group by itemid)
retourneert één record – het record met de maximale stemdatum.

Other episodes