2016-09-27 1 views
0

J'ai une table comme suitQuelle est la meilleure façon de sélectionner 2 rangs de table dans une rangée?

TABLE_A 
ID   PERSON_ID NAME   GRADE 
---------- ---------- ---------- ---------- 
1   1   NAME_1  10 
2   1   NAME_1  20 
3   2   NAME_2  30 
4   2   NAME_2  40 
... 

dans ce tableau, pour chaque nom il y a exactement deux lignes (deux classes). Je veux faire une requête qui se traduit comme suit

RESULT 
PERSON_ID NAME   GRADE1  GRADE_2 
---------- ---------- ---------- ---------- 
1   NAME_1  10   20 
2   NAME_2  30   40 

Quel est le meilleur pour cette façon. Je peux utiliser l'auto rejoindre, mais je pense que ce n'est pas bonne méthode

+0

Comment calculer GRADE1 et GRADE_2 ?? – Esty

+0

Ooo. Je pense que le nom de Lase sera Name_2. – Esty

+0

Utilisez-vous MySQL ou Postgresql? (Ne marquez pas les produits non impliqués.) – jarlh

Répondre

-2

J'ai trouvé la meilleure réponse pour PostgreSQL ce lien https://www.postgresql.org/docs/9.2/static/tablefunc.html Dans PostgreSQL il y a la fonction crosstab(text).

La fonction de tableau croisé est utilisée pour produire des affichages «pivotants», dans lesquels les données sont répertoriées sur la page plutôt que vers le bas. Par exemple, nous pourrions avoir des données comme

row1 val11 
row1 val12 
row1 val13 
... 
row2 val21 
row2 val22 
row2 val23 
... 

que nous souhaitons afficher comme

row1 val11 val12 val13 ... 
row2 val21 val22 val23 ... 
... 

La fonction crosstab prend un paramètre de texte qui est une requête SQL production brute données formatées de la première façon, et produit une table formatée de la deuxième manière. Le paramètre sql est une instruction SQL qui produit l'ensemble de données source. Cette instruction doit renvoyer une colonne row_name, une colonne category et une colonne value. N est un paramètre obsolète, ignoré s'il est fourni (auparavant, il devait correspondre au nombre de colonnes de valeurs de sortie, mais maintenant cela est déterminé par la requête d'appel). Par exemple, la requête fournie peut produire un ensemble quelque chose comme:

row_name cat value 
----------+-------+------- 
    row1  cat1 val1 
    row1  cat2 val2 
    row1  cat3 val3 
    row1  cat4 val4 
    row2  cat1 val5 
    row2  cat2 val6 
    row2  cat3 val7 
    row2  cat4 val8 

La fonction crosstab est déclarée revenir setof record, de sorte que les noms et types réels des colonnes de sortie doivent être définies dans le FROM clause de la déclaration appelant SELECT, par exemple:

SELECT * FROM crosstab('...') AS ct(row_name text, category_1 text, category_2 text); 

Cet exemple produit un ensemble quelque chose comme:

  <== value columns ==> 
row_name category_1 category_2 
----------+------------+------------ 
    row1  val1   val2 
    row2  val5   val6 

section Pour plus de lecture F.35.1.2. dans l'URL entré en haut de la réponse

0

Essayez ceci pour SQL Server

; WITH CTE AS(
SELECT PERSON_ID, NAME, GRADE AS GRADE_1, 
LEAD(GRADE) OVER(PARTITION BY NAME ORDER BY NAME) AS GRADE_2 
FROM TABLE_A 
) 
SELECT * FROM CTE 
WHERE GRADE_2 IS NOT NULL 

RESULT SET: 

PERSON_ID NAME   GRADE_1  GRADE_2 
---------- ---------- ---------- ---------- 
1   NAME_1  10   20 
2   NAME_2  30   40 
+0

Est-ce une réponse MySQL ou Postgresql (ou les deux)? – jarlh

0

Si vous utilisez MySQL, et si tous les noms ont exactement deux dossiers, et la première année est l'un avec l'identifiant inférieur et la deuxième année de l'autre, alors vous pouvez utiliser une requête comme celle-ci:

select 
    person_id, 
    name, 
    group_concat(grade order by id) as grades 
from 
    table_a 
group by 
    person_id, 
    name 

alors si vous voulez séparer les grades en deux nouvelles colonnes, vous pouvez utiliser SUBSTRING_INDEX:

select 
    person_id, 
    name, 
    substring_index(group_concat(grade order by id), ',', 1) as grade1, 
    substring_index(group_concat(grade order by id), ',', -1) as grade2 
from 
    table_a 
group by 
    person_id, 
    name 
1

Vous pouvez utiliser GROUP BY comme autre personne suggérée.

Ou vous pouvez faire une jointure.

select t1.person_id, t1.grade as grade1, t2.grade as grade2 
from TABLE_A t1 join TABLE_A t2 on t1.person_id=t2.person_id and t1.id!=t2.id 

Cette join assemble toutes les lignes avec la même personne, mais pas les lignes avec le même identifiant si vous filtrez les doublons.

+1

approche intéressante :) je pense que vous devriez utiliser '.. et t1.id

SELECT PERSON_ID, 
     MAX(NAME) as NAME, 
     MIN(GRADE) as GRADE1, 
     MAX(GRADE) as GRADE2 
FROM TABLE_A 
GROUP BY PERSON_ID