简体   繁体   中英

SQL query to get data between 2 date valid time table

I need to get georgi facello salary data when margareta is manager.

this is position (titles tbl) table :

___________________________________________________
| name      | title     | from_date   | to_date    |
----------------------------------------------------
| Margareta | Manager   | 1985-01-01  | 1991-10-01 |

and here is employee salary table:

___________________________________________________
| name         | salary   | from_date   | to_date  |
----------------------------------------------------
Georgi Facello      60117   1986-06-26  1987-06-26
Georgi Facello      62102   1987-06-26  1988-06-25
Georgi Facello      66074   1988-06-25  1989-06-25
Georgi Facello      66596   1989-06-25  1990-06-25
Georgi Facello      66961   1990-06-25  1991-06-25
Georgi Facello      71046   1991-06-25  1992-06-24
Georgi Facello      74333   1992-06-24  1993-06-24
Georgi Facello      75286   1993-06-24  1994-06-24
Georgi Facello      75994   1994-06-24  1995-06-24
Georgi Facello      76884   1995-06-24  1996-06-23
Georgi Facello      80013   1996-06-23  1997-06-23
Georgi Facello      81025   1997-06-23  1998-06-23
Georgi Facello      81097   1998-06-23  1999-06-23
Georgi Facello      84917   1999-06-23  2000-06-22
Georgi Facello      85112   2000-06-22  2001-06-22
Georgi Facello      85097   2001-06-22  2002-06-22
Georgi Facello      88958   2002-06-22  9999-01-01

so my query is

SELECT employees.name, salaries.*
FROM salaries
INNER JOIN employees ON employees.emp_no = salaries.emp_no
WHERE salaries.from_date >= (
    SELECT titles.from_date
    FROM titles 
    JOIN employees ON employees.emp_no = titles.emp_no
    WHERE titles.title = 'manager' AND employees.name = 'margareta markovitch'
) 
AND salaries.to_date <= (
    SELECT titles.to_date
    FROM titles 
    JOIN employees ON employees.emp_no = titles.emp_no
    WHERE titles.title = 'manager' AND employees.name = 'margareta markovitch'
) 

and here is the result

 ___________________________________________________
| name         | salary   | from_date   | to_date  |
----------------------------------------------------
Georgi Facello      60117   1986-06-26  1987-06-26
Georgi Facello      62102   1987-06-26  1988-06-25
Georgi Facello      66074   1988-06-25  1989-06-25
Georgi Facello      66596   1989-06-25  1990-06-25
Georgi Facello      66961   1990-06-25  1991-06-25

the problem is one row not include in result :

Georgi Facello      71046   1991-06-25  1992-06-24

Which is still valid because margareta is still a manager until oct'91

Do you have suggestion from this problem?

You are very close. Just need to to include all the overlapping period:

 SELECT DISTINCT employees.name, salaries.*
    FROM salaries
    INNER JOIN employees ON employees.emp_no = salaries.emp_no
    WHERE salaries.from_date < (
        SELECT titles.to_date
        FROM titles 
        JOIN employees ON employees.emp_no = titles.emp_no
        WHERE titles.title = 'manager' AND employees.name = 'margareta markovitch'
    ) 
    AND salaries.to_date > (
        SELECT titles.from_date
        FROM titles 
        JOIN employees ON employees.emp_no = titles.emp_no
        WHERE titles.title = 'manager' AND employees.name = 'margareta markovitch'
    ) 

Alternative answer to PeterHe's, if you're only concerned with if a year started while Margareta was manager, compare against only the from_date, and disregard the to_date:

SELECT employees.name, salaries.*
FROM salaries
INNER JOIN employees ON employees.emp_no = salaries.emp_no
WHERE salaries.from_date >= (
    SELECT titles.from_date
    FROM titles 
    JOIN employees ON employees.emp_no = titles.emp_no
    WHERE titles.title = 'manager' AND employees.name = 'margareta markovitch'
) 
AND salaries.from_date <= (
    SELECT titles.to_date
    FROM titles 
    JOIN employees ON employees.emp_no = titles.emp_no
    WHERE titles.title = 'manager' AND employees.name = 'margareta markovitch'
) 

This returns all entries where a year started while Margareta was manager.

If less code is your thing...

DROP TABLE IF EXISTS titles;

CREATE TABLE titles
(name VARCHAR(12) NOT NULL 
,title VARCHAR(12) NOT NULL
,from_date DATE NOT NULL
,to_date DATE NOT NULL
);


INSERT INTO titles VALUES
('Margareta','Manager','1985-01-01','1991-10-01');

DROP TABLE IF EXISTS salaries;

CREATE TABLE salaries
(name VARCHAR(30) NOT NULL 
,salary INT NOT NULL
,from_date DATE NOT NULL
,to_date DATE NOT NULL
,PRIMARY KEY(name,from_date)
);

INSERT INTO salaries VALUES
('Georgi Fecello',60117,'1986-06-26','1987-06-26'),
('Georgi Fecello',62102,'1987-06-26','1988-06-25'),
('Georgi Fecello',66074,'1988-06-25','1989-06-25'),
('Georgi Fecello',66596,'1989-06-25','1990-06-25'),
('Georgi Fecello',66961,'1990-06-25','1991-06-25'),
('Georgi Fecello',71046,'1991-06-25','1992-06-24'),
('Georgi Fecello',74333,'1992-06-24','1993-06-24'),
('Georgi Fecello',75286,'1993-06-24','1994-06-24'),
('Georgi Fecello',75994,'1994-06-24','1995-06-24'),
('Georgi Fecello',76884,'1995-06-24','1996-06-23'),
('Georgi Fecello',80013,'1996-06-23','1997-06-23'),
('Georgi Fecello',81025,'1997-06-23','1998-06-23'),
('Georgi Fecello',81097,'1998-06-23','1999-06-23'),
('Georgi Fecello',84917,'1999-06-23','2000-06-22'),
('Georgi Fecello',85112,'2000-06-22','2001-06-22'),
('Georgi Fecello',85097,'2001-06-22','2002-06-22');

SELECT s.* 
  FROM titles t 
  JOIN salaries s 
    ON s.from_date <= t.to_date 
   AND s.to_date >= t.from_date;
+----------------+--------+------------+------------+
| name           | salary | from_date  | to_date    |
+----------------+--------+------------+------------+
| Georgi Fecello |  60117 | 1986-06-26 | 1987-06-26 |
| Georgi Fecello |  62102 | 1987-06-26 | 1988-06-25 |
| Georgi Fecello |  66074 | 1988-06-25 | 1989-06-25 |
| Georgi Fecello |  66596 | 1989-06-25 | 1990-06-25 |
| Georgi Fecello |  66961 | 1990-06-25 | 1991-06-25 |
| Georgi Fecello |  71046 | 1991-06-25 | 1992-06-24 |
+----------------+--------+------------+------------+

You can separate all dates and check if from or to date is within that table:

DECLARE @employees TABLE
(
    emp_no INT,
    name NVARCHAR(MAX),
    title NVARCHAR(MAX),
    from_date DATE,
    to_date DATE
)

DECLARE @salaries TABLE
(
    emp_no INT,
    salary INT,
    from_date DATE,
    to_date DATE
)

INSERT INTO @employees VALUES
(1,'Margareta','Manager','1985-01-01','1991-10-01'),
(2,'Georgi Facello','Employee','1986-06-26','2002-06-22')

INSERT INTO @salaries VALUES
(2,60117,'1986-06-26','1987-06-26'),
(2,62102,'1987-06-26','1988-06-25'),
(2,66074,'1988-06-25','1989-06-25'),
(2,66596,'1989-06-25','1990-06-25'),
(2,66961,'1990-06-25','1991-06-25'),
(2,71046,'1991-06-25','1992-06-24'),
(2,74333,'1992-06-24','1993-06-24'),
(2,75286,'1993-06-24','1994-06-24'),
(2,75994,'1994-06-24','1995-06-24'),
(2,76884,'1995-06-24','1996-06-23'),
(2,80013,'1996-06-23','1997-06-23'),
(2,81025,'1997-06-23','1998-06-23'),
(2,81097,'1998-06-23','1999-06-23'),
(2,84917,'1999-06-23','2000-06-22'),
(2,85112,'2000-06-22','2001-06-22'),
(2,85097,'2001-06-22','2002-06-22')

DECLARE @from_date DATE = (SELECT from_date FROM @employees WHERE title = 'Manager' AND name = 'Margareta')
DECLARE @to_date DATE = (SELECT to_date FROM @employees WHERE title = 'Manager' AND name = 'Margareta')

DECLARE @dates TABLE ( singleDate DATE )

INSERT INTO @dates
SELECT  TOP (DATEDIFF(DAY, @from_date, @to_date) + 1)
        Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @from_date)
FROM    sys.all_objects a
        CROSS JOIN sys.all_objects b

SELECT E.name,S.* FROM @salaries S
LEFT JOIN @employees E ON S.emp_no = E.emp_no
WHERE S.from_date IN (SELECT singleDate FROM @dates)
OR S.to_date IN (SELECT singleDate FROM @dates)

OUTPUT:

name    emp_no  salary  from_date   to_date
Georgi Facello  2   60117   1986-06-26  1987-06-26
Georgi Facello  2   62102   1987-06-26  1988-06-25
Georgi Facello  2   66074   1988-06-25  1989-06-25
Georgi Facello  2   66596   1989-06-25  1990-06-25
Georgi Facello  2   66961   1990-06-25  1991-06-25
Georgi Facello  2   71046   1991-06-25  1992-06-24

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM