2017-03-23 6 views
3

Ich verwende SQL Server in einem C# -Projekt für ein Problembehandlungsprogramm, und ich habe eine Tabelle, die ID, Frage, QuestionId, Lösung und Rang enthält. Ich möchte, dass es mehrere Lösungen für ein Problem gibt und das Programm wählt die am besten bewertete Lösung, die nur durch die höchste Nummer ausgewählt wird, die jedes Mal erhöht wird, wenn sie korrekt ist. Dazu habe ich die folgende SQL-Anweisung:SQL-Anweisung, die nicht ausgewählt wird

sql = "SELECT Solution FROM dbo.Questions WHERE Rank=(SELECT MAX(Rank) FROM 
dbo.Questions) AND QuestionId =" + questionId; 

Als ich hatte nur eine Lösung zur Verfügung dies funktionierte gut, aber wenn ich mehrere Lösungen ist es nicht.

+1

'SELECT MAX (Rang) VON dbo.VideoPlayer' gibt das Maximum von * all *' QuestionIds' zurück. Wenn es dann nicht mit dem Rang der spezifischen questionId übereinstimmt, nach der Sie suchen, erhalten Sie keine Zeilen. –

Antwort

6

Sie müssen richtig Ihre Anfragen parametrieren Bobby Tables: A guide to preventing SQL injection

sql = "SELECT Solution FROM dbo.Questions q WHERE Rank=(SELECT MAX(Rank) FROM 
dbo.Questions i where i.QuestionId = q.QuestionId) AND q.QuestionId =" + questionId; 

Dies stellt sicher, dass die max(rank) von der Unterabfrage zurückgegeben wird, ist die max(rank) der Lösung für die QuestionId Sie abfragen für.

Sie auch dies tun können, wenn Sie nur einen wollen Solution:

select top 1 Solution 
from dbo.Questions q 
where QuestionId = @QuestionId 
order by [Rank] desc 
+0

Das hat bei mir funktioniert, vielen Dank! – Niall

+0

@Niall Glücklich zu helfen! Und bitte parametriere deine Abfragen anstatt die Verkettung zu verwenden. – SqlZim

0

Der Datensatz hat die MAX Rang möglicherweise nicht die QuestionID haben Sie in der gegebenen UND QuestionID =“+ QuestionID;.

-2

Bitte ändern Sie Ihre Anfrage wie folgt.

sql = "SELECT Solution FROM dbo.Questions WHERE Rank in (SELECT MAX(Rank) FROM 
dbo.Questions) AND QuestionId =" + questionId; 

Hier habe ich geändert, wo Rang „in“ statt „=“

+0

Dies wird immer noch den maximalen Rang aller möglichen Fragen auswählen! – Jamiec

+1

Ich kann eine Begründung nicht rechtfertigen, weil sie nicht nur die Frage nicht beantwortet, sondern auch gefährliche SQL-Praktiken erzwingt ... – user2366842

4

Sie die Auswahl des max Ranges alle Lösungen und die Suche nach der Lösung an eine bestimmte Frage mit diesem Rang.

beginnen am Anfang - wählen Sie die möglichen Lösungen in einem WAK

with solutions as(
    SELECT Solution, Rank FROM dbo.Questions WHERE QuestionId = @questionId 
) 
... more to come 

Da Sie eine ranking function alle möglichen Lösungen Rang verwenden können, nach Rang und wählen Sie das mit dem besten Rang (zu viele Reihen in diesem Satz)

with solutions as(
    SELECT Solution, Rank() OVER (ORDER BY Rank DESC) as rank 
    FROM dbo.Questions WHERE QuestionId = @questionId 
) 
SELECT * FROM solutions WHERE rank = 1 

Diese sieht nicht Abdeckung 2 Lösungen einen gleichen Rang haben - Sie werden 2 Ergebnisse aus der Abfrage, wenn zwei den gleichen Rang haben. Zwei Lösungen gibt es - in Betracht ziehen, beide zu verwenden.

  1. Wählen Sie eine Tie-Break-Säule - vielleicht die letzte - durch eine zweite Säule in die ORDER BY Zugabe (...RANK() OVER (ORDER BY rank DESC, CreatedDate DESC)
  2. eine TOP 1 in die letzte Auswahl Werfen (SELECT TOP 1 * FROM solutions WHERE rank = 1)
0

Sie könnten versuchen, diese Ich habe die Where-Klausel außerhalb der CTE-Abfrage verlassen, so dass Sie die Abfrage auch verwenden können, um eine vollständige Liste jeder Frage mit ihrem maximalen Rang zu erhalten (wenn Sie den questionId-Filter auslassen):

with [ctreMaxSolution] as 
    (
     select [QuestionId] 
       , max([Rank]) as [Rank] 
     from [dbo].[Questions] 
     group by [QuestionId] 
    ) 
    select * 
    from [dbo].[Questions] as [q] 
      inner join [cteMaxSolution] as [cms] on [q].[QuestionId] = [cms].[QuestionId] 
               and [q].[Rank] = [cms].[Rank] 
    where [q].[QuestionId] = @questionId; 

Ich habe eine SQL Server-Variable dort verwendet, aber Sie können eine gespeicherte Prozedur daraus machen oder sie in eine Ad-hoc-Abfrage wie in Ihrer Frage konvertieren, ganz bei Ihnen.

0

Zuerst machen Sie einen Filter von "questionId" und dann "Reihenfolge von" Rang.

versuchen mit diesem:

SELECT TOP 1 q.solution FROM dbo.Questions q WHERE q.QuestionId = @QuestionId 
ORDER BY q.Rank desc 

Hope this Hilfe!

Verwandte Themen