Je serais ravi de poser ma première question sur StackOverflow.
J'ai deux tables (employés et salaires) dans ma base de données (employés).
La table des employés ressemble à ceci:
+--------+------------+-----------+-----------------+ | emp_no | first_name | last_name | Salary_for_1990 | +--------+------------+-----------+-----------------+ | 10001 | Georgi | Facello | 66961 | | 10004 | Christian | Koblick | 48271 | | 10005 | Kyoichi | Maliniak | 82621 | | 10006 | Anneke | Preusig | 40000 | | 10007 | Tzvetan | Zielinski | 60740 | | 10009 | Sumant | Peace | 70889 | | 10011 | Mary | Sluis | 42365 | | 10013 | Eberhardt | Terkki | 46305 | | 10018 | Kazuhide | Peha | 61648 | | 10021 | Ramzi | Erde | 59700 | +--------+------------+-----------+-----------------+
La table des salaires ressemble à ceci:
SELECT
e.emp_no,
e.first_name,
e.last_name,
s.salary AS Salary_for_1990
FROM
employees e
JOIN
salaries s ON e.emp_no = s.emp_no
WHERE
from_date BETWEEN '1990-01-01' AND '1990-12-31'
GROUP BY e.emp_no
ORDER BY e.emp_no ASC
LIMIT 10;
Je souhaite renvoyer des valeurs pour un intervalle de dates spécifique. Par exemple, je veux savoir quel salaire un employé avait pour un intervalle dans une vue dynamique, pour les années 1990-1991 pour les années 1991-1992, etc.
J'ai écrit la requête suivante: p >
+-----------+------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------+------+------+-----+---------+-------+ | emp_no | int | NO | PRI | NULL | | | salary | int | NO | | NULL | | | from_date | date | NO | PRI | NULL | | | to_date | date | NO | | NULL | | +-----------+------+------+-----+---------+-------+
J'ai obtenu le résultat suivant:
+------------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+---------------+------+-----+---------+-------+ | emp_no | int | NO | PRI | NULL | | | first_name | varchar(14) | NO | | NULL | | | last_name | varchar(16) | NO | | NULL | | +------------+---------------+------+-----+---------+-------+
Cela fonctionne donc pour une seule valeur '1990-1991' années, cependant, Je cherche la possibilité d'ajouter dans la requête une colonne supplémentaire pour les années '1991-1992', '1992-1993', etc pour pouvoir voir la croissance dynamique des salaires des employés.
J'ai pensé aux variables, mais je ne sais pas comment l'interroger dans le contexte.
J'attends vos réponses avec impatience.
Merci d'avance.
3 Réponses :
Les sous-requêtes sont une possibilité simple, bien qu'elles ne soient pas très élégantes et ne s'adaptent pas bien avec de nombreuses années:
SELECT e.emp_no, e.first_name, e.last_name, (SELECT s.salary FROM salaries s WHERE s.emp_no = e.emp_no AND from_date BETWEEN '1990-01-01' AND '1990-12-31') Salary_for_1990, (SELECT s.salary FROM salaries s WHERE s.emp_no = e.emp_no AND from_date BETWEEN '1991-01-01' AND '1991-12-31') Salary_for_1991 ...
Quel est l'intérêt de donner des salaires et l'alias des s et de ne pas les utiliser
Bien sûr, vous avez raison. Je l'ai corrigé. Je ne suis pas un grand fan des alias, mais je l'ai ajouté pour répondre à la question.
Merci pour votre réponse. Pouvez-vous me suggérer comment le rendre évolutif afin d'améliorer sa convivialité?
Si une mise à l'échelle est nécessaire, consultez: stackoverflow.com/questions / 12382771 / mysql-pivot-crosstab-qu ery
Si vous souhaitez rendre cette fonction "évolutive", vous devez utiliser une agrégation conditionnelle et des instructions préparées, par exemple
drop table if exists t;
create table t(emp int,dt date,salary int);
insert into t values
(1,'2015-06-30',7),
(1,'2015-12-31',10),
(1,'2016-12-31',05),
(1,'2017-12-31',10),
(2,'2015-12-31',20),
(2,'2016-12-31',25),
(2,'2017-12-31',30);
set @sql =
(select group_concat(concat('max(case when year(dt) = ',dt ,' then salary else 0 end) as ', 'yr',dt))
from
(
select distinct year(dt) dt from t
) s
)
;
set @sql = (select concat('Select emp,',@sql,' from t group by emp'));
prepare sqlstmt from @sql;
execute sqlstmt;
deallocate prepare sqlstmt;
+------+--------+--------+--------+
| emp | yr2015 | yr2016 | yr2017 |
+------+--------+--------+--------+
| 1 | 10 | 5 | 10 |
| 2 | 20 | 25 | 30 |
+------+--------+--------+--------+
2 rows in set (0.00 sec)
Notez que cela renverra le salaire MAX pour une année donnée.
Les gens ont un salaire à une date qui ne correspond pas à une plage de dates.
Pour votre problème, vous pouvez utiliser l'agrégation conditionnelle:
SELECT e.emp_no, e.first_name, e.last_name,
MAX(CASE WHEN from_date <= '1990-01-01' AND to_date > '1990-01-01' THEN salary END) as salary_19900101,
MAX(CASE WHEN from_date <= '1991-01-01' AND to_date > '1991-01-01' THEN salary END) as salary_19910101,
MAX(CASE WHEN from_date <= '1992-01-01' AND to_date > '1991-02-01' THEN salary END) as salary_19910101
FROM employees e JOIN
salaries s
ON e.emp_no = s.emp_no
GROUP BY e.emp_no, e.first_name, e.last_name
ORDER BY e.emp_no ASC
LIMIT 10;
NULL . GROUP BY contient toutes les colonnes non agrégées. Bien que cela ne soit pas formellement requis si emp_no est la clé primaire, c'est une bonne habitude si vous apprenez SQL.
Et si un employé avait un changement de salaire le 1er mars 1991: que voulez-vous afficher pour l'année 1991?
En général, vous
GROUP BYles mêmes colonnes que vousSELECT, sauf celles qui sont des arguments pour définir des fonctions.Et comment voulez-vous voir le résultat de cette nouvelle requête
Votre sélection / idée n'est pas correcte. Imaginez un employé senior qui a le même salaire de 1985 à aujourd'hui. Il ne sera pas dans le résultat.
GMB Je ne recherche pas de résultat précis. Observez simplement sa dynamique brute.
jarlh que suggéreriez-vous de faire à la place?
RiggsFolly Je veux ajouter de nouvelles colonnes comme nouvel intervalle par exemple pour 1994-1995 etc. Et observer sa dynamique
MichalSv Comme le montre la requête, l'employé principal démontrera le même salaire ou je ne vous ai pas répondu correctement.