2014-05-24 17 views
13

Gestern in einem Bewerbungsgespräch wurde mir diese Frage gestellt und ich hatte keine Ahnung davon. Angenommen, ich habe ein Wort "Manhattan". Ich möchte nur die Buchstaben "M", "A", "N", "H", "T" in SQL anzeigen. Wie es geht? Jede Hilfe wird geschätzt.Wie kann man einzelne Buchstaben eines Wortes in SQL aufteilen und anzeigen?

+3

konstruieren würde ich wahrscheinlich eine gespeicherte Prozedur schreiben, dies zu tun, aber nur, wenn ich habe SQL zu verwenden. Ansonsten würde ich eine tatsächliche Programmiersprache verwenden. – Ellesedil

+1

Aktuelle Programmiersprachen machen diesen Job einfacher. Aber wie geht das in SQL? Bitte zeig es mir durch. – StrugglingCoder

+0

Für * welche * SQL-Implementierung? – user2864740

Antwort

12

Nun, hier ist meine Lösung (sqlfiddle) - es zielt darauf ab, eine "Relational SQL" -Operationen zu verwenden, die wurden, was der Interviewer konzeptionell ging.

Die meiste Arbeit ist einfach, um die Zeichenfolge in eine Reihe von (Pos, Brief) Aufzeichnungen zu verwandeln, da die relevante endgültige angewendet DQL ist eine bloße SELECT mit einer Gruppierung und Bestellung angewendet.

select letter 
from (
    -- All of this just to get a set of (pos, letter) 
    select ns.n as pos, substring(ss.s, ns.n, 1) as letter 
    from (select 'MANHATTAN' as s) as ss 
    cross join (
    -- Or use another form to create a "numbers table" 
    select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9)) as X(n) 
    ) as ns 
) as pairs 
group by letter -- guarantees distinctness 
order by min(pos) -- ensure output is ordered MANHT 

Die obige Abfrage funktioniert in SQL Server 2008, aber die "Numbers Table" kann für andere Anbieter geändert werden müssen. Ansonsten wird nichts verwendet, das anbieterspezifisch ist - kein CTE oder eine Anwendung einer Funktion oder eines prozeduralen Sprachcodes.

Das oben Gesagte ist ein konzeptioneller Ansatz, für den SQL entwickelt wurde Sätze und Beziehungen und Multiplizität über Datensätze hinweg; das obige Beispiel ist in gewisser Hinsicht nur eine Perversion von solchem.


Prüfung der Zwischenbeziehung,

select ns.n as pos, substring(ss.s, ns.n, 1) as letter 
    from (select 'MANHATTAN' as s) as ss 
    cross join (
    select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9)) as X(n) 
    ) as ns 

verwendet ein cross join das kartesische Produkt der Saite (1 Zeile) mit den Zahlen (9 Zeilen) zu erzeugen; Die substring Funktion wird dann mit der Zeichenfolge und jede Nummer angewendet, um jedes Zeichen in Übereinstimmung mit seiner Position zu erhalten.Der resultierende Satz enthält die Records-

POS LETTER 
1 M 
2 A 
3 N 
.. 
9 N 

dann wird die äußere Auswahlgruppen jeder Datensatz auf den Buchstaben nach und die resultierenden Aufzeichnungen werden durch das Minimum (erste) Auftrittsposition des Briefes angeordnet, dass die Gruppierung zur Gründung. (Ohne die Reihenfolge durch die Briefe wäre eindeutig gewesen aber die endgültige Bestellung wäre nicht garantiert.)

+0

Bitte entschuldigen Sie meinen Intellekt ... können Sie nur die Schritte bitte erklären? Ein wenig mehr – StrugglingCoder

+0

@ user3655102 Ich habe ein bisschen mehr Erklärung hinzugefügt - hoffe, es klärt die Dinge auf. – user2864740

+0

Ich wundere mich, warum Sie die '(7)' übersprungen haben, und ich denke Lösung ist für 9 Zeichen langes Wort nur. – sallushan

3
declare @charr varchar(99) 
declare @lp int 
set @charr='Manhattan' 
set @lp=1 

DECLARE @T1 TABLE (
FLD VARCHAR(max) 
) 

while(@lp<=LEN(@charr)) 
begin 
    if(not exists(select * from @T1 where FLD=(select SUBSTRING(@charr,@lp,1)))) 
    begin 
     insert into @T1 
     select SUBSTRING(@charr,@lp,1) 
    end 
    set @[email protected]+1 

end 

select * from @T1 

Check dies kann es u

+0

Ja, aber wird es verschiedene auswählen? d. h. A würde 2 mal kommen. T würde auch zweimal kommen. Recht? – StrugglingCoder

+1

Ich habe meine Antwort geändert chk jetzt –

+0

Stellen Sie sicher, um welche SQL-Implementierung (en) dies funktioniert zu spezifizieren. – user2864740

7

Ein Weg helfen (wenn SQL Server) mit einem recursive CTE (Commom Table Expression) ist.

DECLARE @source nvarchar(100) = 'MANHATTAN' 
; 
WITH cte AS (
    SELECT SUBSTRING(@source, 1, 1) AS c1, 1 as Pos 
    WHERE LEN(@source) > 0 
    UNION ALL 
    SELECT SUBSTRING(@source, Pos + 1, 1) AS c1, Pos + 1 as Pos 
    FROM cte 
    WHERE Pos < LEN(@source) 
) 
SELECT DISTINCT c1 from cte 

SqlFiddle for this is here. Ich musste die @source für SqlFiddle inline, aber der obige Code funktioniert gut in Sql Server. Die erste SELECT generiert die erste Zeile (in diesem Fall 'M', 1). Der zweite SELECT ist der rekursive Teil, der die nachfolgenden Zeilen generiert, wobei die Pos Spalte jedes Mal inkrementiert wird, bis die Beendigungsbedingung WHERE Pos < LEN(@source) schließlich erfüllt ist. Die letzte Auswahl entfernt die Duplikate. Intern sortiert SELECT DISTINCT die Zeilen, um das Entfernen von Duplikaten zu erleichtern, weshalb die endgültige Ausgabe in alphabetischer Reihenfolge erfolgt. Da Sie die Reihenfolge nicht als Anforderung angegeben haben, habe ich sie unverändert belassen. Aber Sie könnten es ändern, um stattdessen eine GROUP zu verwenden, die auf MIN(Pos) bestellt wurde, wenn Sie die Ausgabe in der ursprünglichen Reihenfolge der Zeichen benötigten.

Dieselbe Technik kann für Dinge wie das Generieren aller Bigrams für eine Zeichenfolge verwendet werden, mit einer kleinen Änderung der allgemeinen Struktur oben.

3

Hier ist eine Oracle-Version von @ user2864740 's Antwort. Der einzige Unterschied ist, wie Sie die „Zahlen Tabelle“ (plus geringfügige Unterschiede in Aliasing)

select letter 
from (
    select ns.n as pos, substr(ss.s, ns.n, 1) as letter 
    from (select 'MANHATTAN' as s from dual) ss 
    cross join (
    SELECT LEVEL as n 
    FROM DUAL 
    CONNECT BY LEVEL <= 9 
    ORDER BY LEVEL) ns 
) pairs 
group by letter  
order by min(pos) 
Verwandte Themen