sqlite2: Collage valeurs maximum par colonne d'une autre table (référence de la sous-requête)?

StackOverflow https://stackoverflow.com/questions/3940973

  •  30-09-2019
  •  | 
  •  

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!

Était-ce utile?

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        
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top