sqlite2: Collage valeurs maximum par colonne d'une autre table (référence de la sous-requête)?
Question
J'utilise la base de données suivante:
CREATE TABLE datas (d_id INTEGER PRIMARY KEY, name_id numeric, countdata numeric);
INSERT INTO datas VALUES(1,1,20); //(NULL,1,20);
INSERT INTO datas VALUES(2,1,47); //(NULL,1,47);
INSERT INTO datas VALUES(3,2,36); //(NULL,2,36);
INSERT INTO datas VALUES(4,2,58); //(NULL,2,58);
INSERT INTO datas VALUES(5,2,87); //(NULL,2,87);
CREATE TABLE names (n_id INTEGER PRIMARY KEY, name text);
INSERT INTO names VALUES(1,'nameA'); //(NULL,'nameA');
INSERT INTO names VALUES(2,'nameB'); //(NULL,'nameB');
Ce que je voudrais faire, est de sélectionner toutes les valeurs (lignes) de names
- auquel toutes les colonnes de datas
seront ajoutés, pour la ligne où datas
.countdata
est maximale pour n_id
(et bien sûr, où name_id = n_id
) .
Je peux y arriver un peu avec la requête suivante:
sqlite> .header ON
sqlite> SELECT * FROM names AS n1
LEFT OUTER JOIN (
SELECT d_id, name_id, countdata FROM datas AS d1
WHERE d1.countdata IN (
SELECT MAX(countdata) FROM datas
WHERE name_id=1
)
) AS p1 ON n_id=name_id;
n1.n_id|n1.name|p1.d_id|p1.name_id|p1.countdata
1|nameA|2|1|47
2|nameB|||
... mais - évidemment -. Il ne fonctionne que pour une seule ligne (celle explicitement définie par name_id=1
)
Le problème est, la requête SQL échoue chaque fois que je tente de faire référence en quelque sorte le n_id
« courant »:
sqlite> SELECT * FROM names AS n1
LEFT OUTER JOIN (
SELECT d_id, name_id, countdata FROM datas AS d1
WHERE d1.countdata IN (
SELECT MAX(countdata) FROM datas
WHERE name_id=n1.n_id
)
) AS p1 ON n_id=name_id;
SQL error: no such column: n1.n_id
Est-il possible de réaliser ce que je veux dans sqlite2 ??
Merci à l'avance,
Vive!
La solution
Oh, bien - qui n'était pas banal du tout, mais voici une solution:
sqlite> SELECT * FROM names AS n1
LEFT OUTER JOIN (
SELECT d1.*
FROM datas AS d1, (
SELECT max(countdata) as countdata,name_id
FROM datas
GROUP BY name_id
) AS ttemp
WHERE d1.name_id = ttemp.name_id AND d1.countdata = ttemp.countdata
) AS p1 ON n1.n_id=p1.name_id;
n1.n n1.name p1.d_id p1.name_id p1.countdata
---- ------------ ---------- ---------- -----------------------------------
1 nameA 2 1 47
2 nameB 5 2 87
Eh bien, espérons que cela finit d'aider quelqu'un, :) Vive!
Remarques : Notez que simplement appeler vis max (de countdata) jusqu'à competely d_id
:
sqlite> select d_id,name_id,max(countdata) as countdata from datas group by name_id;
d_id name_id countdata
---- ------------ ----------
3 2 87
1 1 47
pour obtenir correcte d_id
correspondante, nous devons faire max()
sur datas
séparément - puis effectuez une sorte de Intersection avec le plein datas
( sauf que Intersection en sqlite exige qu'il ya le même nombre de colonnes dans les deux ensembles de données, qui n'est pas le cas ici - et même si nous l'avons fait de cette façon, comme on le voit ci-dessus d_id
sera mal, donc Intersection ne fonctionnera pas ).
Une façon de le faire est à l'aide d'une sorte de table temporaire, puis utiliser une table plusieurs requêtes SELECT de façon à des conditions fixes entre plein datas
et le sous-ensemble retourné par max(countdata)
, comme indiqué ci-dessous:
sqlite> CREATE TABLE ttemp AS SELECT max(countdata) as countdata,name_id FROM datas GROUP BY name_id;
sqlite> SELECT d1.*, ttemp.* FROM datas AS d1, ttemp WHERE d1.name_id = ttemp.name_id AND d1.countdata = ttemp.countdata;
d1.d d1.name_id d1.countda ttemp.coun ttemp.name_id
---- ------------ ---------- ---------- -----------------------------------
2 1 47 47 1
5 2 87 87 2
sqlite> DROP TABLE ttemp;
ou, on peut réécrire ce qui précède donc un sous-requête SELECT est utilisé, comme celui-ci (sous-sélection?):
sqlite> SELECT d1.* FROM datas AS d1, (SELECT max(countdata) as countdata,name_id FROM datas GROUP BY name_id) AS ttemp WHERE d1.name_id = ttemp.name_id AND d1.countdata = ttemp.countdata;
d1.d d1.name_id d1.countda
---- ------------ ----------
2 1 47
5 2 87