2009-08-06 7 views
25

Ich möchte eine Tabelle, die Studenten und die Noten, die sie für alle ihre Fächer erhalten, in einer Abfrage erhalten.Pivot in SQLite

Dies ist meine Tabellenstruktur:

Tabelle: markdetails

## studid ## ## subjectid ## ## marks ## 
    A1   3    50 
    A1   4    60 
    A1   5    70 
    B1   3    60 
    B1   4    80 
    C1   5    95 

Tabelle: student info

tatsächliche Struktur:

## studid ## ## name ## 
     A1   Raam 
     B1   Vivek 
     c1   Alex 

ich das Ergebnis einstellen möchten wie folgt aussehen :

Tabelle: Student Info

## studid ## ## name## ## subjectid_3 ## ## subjectid_4 ## ## subjectid_5 ## 
     A1  Raam  50    60     70 
     B1  Vivek  60    80    null 
     c1  Alex  null    null    95 

Wie kann ich dies in SQLite erreichen?

Antwort

23

Zuerst müssen Sie die aktuelle Tabelle in eine temporäre Tabelle ändern:

alter table student_info rename to student_name 

Dann werden Sie student_info neu erstellen möchten:

create table student_info add column (
    stuid VARCHAR(5) PRIMARY KEY, 
    name VARCHAR(255), 
    subjectid_3 INTEGER, 
    subjectid_4 INTEGER, 
    subjectid_5 INTEGER 
) 

Dann füllen student_info:

insert into student_info 
select 
    u.stuid, 
    u.name, 
    s3.marks as subjectid_3, 
    s4.marks as subjectid_4, 
    s5.marks as subjectid_5 
from 
    student_temp u 
    left outer join markdetails s3 on 
     u.stuid = s3.stuid 
     and s3.subjectid = 3 
    left outer join markdetails s4 on 
     u.stuid = s4.stuid 
     and s4.subjectid = 4 
    left outer join markdetails s5 on 
     u.stuid = s5.stuid 
     and s5.subjectid = 5 

Jetzt lassen Sie einfach Ihre temporäre Tabelle:

drop table student_temp 

Und so können Sie Ihre Tabelle schnell aktualisieren.

SQLite fehlt eine pivot-Funktion, also das Beste, was Sie tun können, ist hart-Code einige Links Joins. A left join bringt alle Zeilen in seinen Join-Bedingungen und gibt null für alle Zeilen aus der ersten oder linken Tabelle zurück, die die Join-Bedingungen für die zweite Tabelle nicht erfüllen.

+0

dank Eric ... die querry für das Erhalten der gesamten Details zu einem student.but gut funktioniert mag ich den Inhalt und Spalten in einer table.I ändern Du hast meine Frage nicht bekommen. Ich will den Tisch wechseln. – arams

+0

Danke ERIC ... Es funktioniert gut. – arams

+0

@arams: Fantastisch, froh, es zu hören! Bitte upvote/markieren Sie dies als die Antwort, wenn es Ihr Problem gelöst hat! – Eric

14

Da der Autor nicht freundlich genug war, dem SQL zu geben, um das Schema zu erstellen, hier ist es für jeden, der die Lösung von @Eric versuchen möchte.

create table markdetails (studid, subjectid, marks); 
create table student_info (studid, name); 

insert into markdetails values('A1', 3, 50); 
insert into markdetails values('A1', 4, 60); 
insert into markdetails values('A1', 5, 70); 
insert into markdetails values('B1', 3, 60); 
insert into markdetails values('B1', 4, 80); 
insert into markdetails values('C1', 5, 95); 

insert into student_info values('A1', 'Raam'); 
insert into student_info values('B1', 'Vivek'); 
insert into student_info values('C1', 'Alex'); 

Hier ist eine alternative Lösung case mit group by verwenden.

select 
    si.studid, 
    si.name, 
    sum(case when md.subjectid = 3 then md.marks end) subjectid_3, 
    sum(case when md.subjectid = 4 then md.marks end) subjectid_4, 
    sum(case when md.subjectid = 5 then md.marks end) subjectid_5 
from student_info si 
join markdetails md on 
     md.studid = si.studid 
group by si.studid, si.name 
; 

Zum Vergleich ist hier die gleiche select-Anweisung von @ Eric Lösung:

select 
    u.stuid, 
    u.name, 
    s3.marks as subjectid_3, 
    s4.marks as subjectid_4, 
    s5.marks as subjectid_5 
from 
    student_temp u 
    left outer join markdetails s3 on 
     u.stuid = s3.stuid 
     and s3.subjectid = 3 
    left outer join markdetails s4 on 
     u.stuid = s4.stuid 
     and s4.subjectid = 4 
    left outer join markdetails s5 on 
     u.stuid = s5.stuid 
     and s5.subjectid = 5 
; 

Es wird interessant sein zu sehen, die man hätte besser durchführen, wenn es eine Menge von Daten ist.

+7

Ich hatte die Möglichkeit, dies auf einer Tabelle mit etwa 150.000 Zeilen zu testen. Eine Komplikation ist, dass ich die Anzahl der Spalten nicht im Voraus kenne, also muss ich ein wenig Vorverarbeitung durchführen, um die Anzahl der benötigten Spalten zu bestimmen. Außerdem haben nicht alle Zeilen die gleiche Anzahl von Daten. Mit der Outer-Join-Methode dauerte mein PC 50 Sekunden. Bei der Methode Methode dauerte es 15 Sekunden. Mit einer Kombination von reshape2 und plyr (ich benutze R um sqlite zu starten), dauerte es ungefähr 1.040 Sekunden. Ihr Kilometerstand kann jedoch variieren. – Chow

+0

@Chow, stimme völlig zu. mein Tisch ist mit 280.000 Zeilen und es dauerte 20 Sekunden. Diese Antwort sollte oben sein. – nikpod

6

großer Anhang! hat mir geholfen, ein ähnliches Problem mit geringem Aufwand und Systemlast zu lösen.Ich bin mit einer Himbeere Pi 1Wire-Schnittstelle DS18B20 Temperatursensordaten wie folgt zu erhalten:

CREATE TABLE temps (Timestamp DATETIME, sensorID TEXT, temperature NUMERIC); 

Beispiel:

sqlite> .headers on 
sqlite> .mode column 
sqlite> select * from temps where timestamp > '2014-02-24 22:00:00'; 

Timestamp   sensorID   temperature 
------------------- --------------- ----------- 
2014-02-24 22:00:02 28-0000055f3f10 19.937 
2014-02-24 22:00:03 28-0000055f0378 19.687 
2014-02-24 22:00:04 28-0000055eb504 19.937 
2014-02-24 22:00:05 28-0000055f92f2 19.937 
2014-02-24 22:00:06 28-0000055eef29 19.812 
2014-02-24 22:00:07 28-0000055f7619 19.625 
2014-02-24 22:00:08 28-0000055edf01 19.687 
2014-02-24 22:00:09 28-0000055effda 19.812 
2014-02-24 22:00:09 28-0000055e5ef2 19.875 
2014-02-24 22:00:10 28-0000055f1b83 19.812 
2014-02-24 22:10:03 28-0000055f3f10 19.937 
2014-02-24 22:10:04 28-0000055f0378 19.75 
2014-02-24 22:10:04 28-0000055eb504 19.937 
2014-02-24 22:10:05 28-0000055f92f2 19.937 

die SUBSTR() Befehl I "Normalisierung" der Zeitstempel bis 10 Minuten bin Perioden. Mit JOIN der SensorID in einen Sensornamen geändert wird, mit der Lookup-Tabelle 'Sensoren'

CREATE VIEW [TempsSlot10min] AS 
SELECT SUBSTR(datetime(timestamp),1,15)||'0:00' AS TimeSlot, 
SensorName, 
temperature FROM 
temps JOIN sensors USING (sensorID, sensorID); 

Beispiel:

sqlite> select * from TempsSlot10min where timeslot >= '2014-02-24 22:00:00'; 

TimeSlot    SensorName temperature 
------------------- ---------- ----------- 
2014-02-24 22:00:00 T1   19.937 
2014-02-24 22:00:00 T2   19.687 
2014-02-24 22:00:00 T3   19.937 
2014-02-24 22:00:00 T4   19.937 
2014-02-24 22:00:00 T5   19.812 
2014-02-24 22:00:00 T6   19.625 
2014-02-24 22:00:00 T10   19.687 
2014-02-24 22:00:00 T9   19.812 
2014-02-24 22:00:00 T8   19.875 
2014-02-24 22:00:00 T7   19.812 
2014-02-24 22:10:00 T1   19.937 
2014-02-24 22:10:00 T2   19.75 
2014-02-24 22:10:00 T3   19.937 
2014-02-24 22:10:00 T4   19.937 
2014-02-24 22:10:00 T5   19.875 

jetzt, passiert die Magie mit der oben CASE-Anweisung erwähnt.

CREATE VIEW [PivotTemps10min] AS 
SELECT TimeSlot, 
AVG(CASE WHEN sensorName = 'T1' THEN temperature END) AS T1, 
AVG(CASE WHEN sensorName = 'T2' THEN temperature END) AS T2, 
... 
AVG(CASE WHEN sensorName = 'T10' THEN temperature END) AS T10 
FROM TempsSlot10min 
GROUP BY TimeSlot; 

Beispiel:

select * from PivotTemps10min where timeslot >= '2014-02-24 22:00:00'; 

TimeSlot    T1   T2    T10 
------------------- ---------- ---------- ... ---------- 
2014-02-24 22:00:00 19.937  19.687   19.687 
2014-02-24 22:10:00 19.937  19.75   19.687 
2014-02-24 22:20:00 19.937  19.75   19.687 
2014-02-24 22:30:00 20.125  19.937   19.937 
2014-02-24 22:40:00 20.187  20.0   19.937 
2014-02-24 22:50:00 20.25  20.062   20.062 
2014-02-24 23:00:00 20.25  20.062   20.062 

Das einzige Problem hier noch ist, dass der Sensorname 'T1' ... 'T10' jetzt in die VIEW fest einprogrammiert wird [PivotTemps10min] und nicht aus der Lookup-Tabelle entnommen .

Trotzdem, vielen Dank für die Antworten in dieser thead!

+0

Das ist wirklich was ich gesucht habe. Vielen Dank. –

+0

Ich bin mir sicher, dass sich eine große Anzahl von IoT-Enthusiasten, die SQL verwenden, darauf beziehen. Meine Bewerbung ist fast genau gleich. – nikpod

0

Wenn Sie eine einfachere Anforderung haben, die Kinder in demselben Feld zu bündeln, ist group_concat Ihr Freund.

Vielen Dank an Simon Slaver aus diesem Thread: http://sqlite.1065341.n5.nabble.com/Howto-pivot-in-SQLite-tp26766p26771.html

+0

Von der [Hilfe] (http://stackoverflow.com/help/how-to-answer): Links zu externen Ressourcen werden empfohlen, aber bitte fügen Sie Kontext um den Link hinzu, so dass Ihre Mitbenutzer eine Idee haben, was es ist und warum es da ist.Zitiere immer den relevantesten Teil eines wichtigen Links, falls die Zielseite nicht erreichbar ist oder permanent offline geschaltet wird. – Adam