Date and value conversion - sql

I'm Inserting the ID's from table2 which is not exist in the table1. Table1 have perfect datatype in date(datetime), Gen(varchar(1)) but Table2 has different datatype for the same column date(varchar(255)), Gen(float) 1-M,2-F.
I share the problem in sample set.
Table1
ID date Gen
193 1996-03-26 00:00:00 M
446 1997-09-20 00:00:00 F
689 1997-02-21 00:00:00 F
612 1993-10-19 00:00:00 M
Table2
ID date Gen
123 1993-03-02 00:00:00 1
456 2019-10-19 11:50:13.913 2
689 1997-02-21 00:00:00 2
789 2019-11-04 08:06:36.71 1
012 2000-10-02 07:11:19 1
I need to append the new ID's in table1. while using the insert query how can I convert the date and Gen variable like table1 format.
Result:
Table1
ID date Gen
193 1996-03-26 00:00:00 M
446 1997-09-20 00:00:00 F
689 1997-02-21 00:00:00 F
612 1993-10-19 00:00:00 M
123 1993-03-02 00:00:00 M
456 2019-10-19 00:00:00 F
789 2019-11-04 00:00:00 M
012 2000-10-02 00:00:00 M

If you want to insert the rows in table2 that are not in table1, you can use insert with filtering logic:
insert into table1 (id, date, gen)
select t2.id, t2.date, (case when gen = 1 then 'M' else 'F' end)
from table2 t2
where not exists (select 1 from table1 t1 where t2.id = t1.id);

Related

SQL get count(*) before several dates

It sounds so simple but I can't figure it out. I have 2 tables:
TABLE 1 contains a list of projects with the dates at which they were approved.
PROJECT
APPROVAL_DATE
A
12/06/2019
A
01/09/2020
A
05/08/2021
A
07/12/2021
B
01/05/2018
B
06/09/2019
B
12/23/2020
TABLE 2 contains dates when tests were performed on these projects.
PROJECT
TEST_DATE
A
01/06/2019
A
01/07/2019
A
02/21/2019
...
...
A
06/22/2021
...
...
B
01/12/2021
...
...
THIS IS WHAT I NEED: For each project, I want to count the total number of tests prior to each APPROVAL_DATE, so I would have this:
PROJECT
APPROVAL_DATE
TOTAL_TESTS_BEFORE_APPROVAL_DATE
A
12/06/2019
1264
A
01/09/2020
1568
A
05/08/2021
1826
A
07/12/2021
2209
B
01/05/2018
560
B
06/09/2019
790
B
12/23/2020
1560
here is how you can do it using left join :
select t1.project, t1.APPROVAL_DATE, count(t2.test_date) TOTAL_TESTS_BEFORE_APPROVAL_DATE
from table1 t1
left join table2 t2
on t1.project = t2.project
and t1.APPROVAL_DATE > t2.TEST_DATE
group by t1.project, t1.APPROVAL_DATE

Access query to return records not found between date range

I have the following sample data
Table1
REF_NO SUPP_START_DATE SUPP_END_DATE
123 01/01/2018 31/12/2018
456 01/01/2017 31/12/2017
789 01/01/2016 31/12/2016
Table2
REF_NO CHG_START_DATE CHG_END_DATE
123 01/03/2018 31/03/2018
123 01/04/2018 30/04/2018
456 01/02/2018 28/02/2018
456 01/01/2017 31/01/2017
789 01/07/2016 31/07/2016
I'd like to know if it is possible to in Access SQL to return all charges (table2) that do not fall between the start and end dates of table1. So, with the sample data above, the following would be returned :-
Results
REF_NO CHG_START_DATE CHG_END_DATE
456 01/02/2018 28/02/2018
I know how to join the 2 tables by using
SELECT table1.ref_no, table2.CHG_START_DATE, table2.CHG_END_DATE
FROM table1
LEFT JOIN table2 ON table1.ref_no = table2.ref_no
but I'm not sure how to cater for the date mismatches
If it is sufficient to just look at the start and end dates:
select t2.*
from table2 t2
where not exists (select 1
from table1 as t1
where t1.refno = t2.refno and
t2.CHG_START_DATE between UPP_START_DATE and SUPP_END_DATE
) or
not exists (select 1
from table1 as t1
where t1.refno = t2.refno and
t2.CHG_END_DATE between UPP_START_DATE and SUPP_END_DATE
) ;
Here's an alternative approach using joins instead of correlated subqueries:
select t2.* from table1 t1 inner join table2 t2 on t1.ref_no = t2.ref_no
where not
(
(t2.chg_start_date between t1.supp_start_date and t1.supp_end_date) and
(t2.chg_end_date between t1.supp_start_date and t1.supp_end_date)
)

Fill postgres table rows with missing column values

I have a PostgreSQL table like this:
table1:
MARKET character varying 10
COST1 Number
MARKET DATE VALUE
A 01/01/2018 10
A 01/02/2018 45
A 01/04/2018 12
B 01/01/2018 12
B 01/05/2018 12
B 01/04/2018 12
I have another table like:
table2:
DATE
01/01/2018
01/02/2018
01/03/2018
01/04/2018
01/05/2018
i am trying to join these two tables such that each "MARKET" from table1 should have all the date ranges in table2. If the "DATE" is not present in table1 its corresponding "VALUE" column should be zero.
OUTPUT should be:
MARKET DATE VALUE
A 01/01/2018 10
A 01/02/2018 45
A 01/03/2018 0
A 01/04/2018 12
A 01/05/2018 0
B 01/01/2018 12
B 01/02/2018 0
B 01/03/2018 0
B 01/04/2018 12
B 01/05/2018 12
Still pretty new to postgres. Any help will be appreciated!
For this type of problem, generate the rows with a cross join. The use another mechanism (left join) to bring in the values.
select m.market, t2.date, coalesce(t1.value, 0) as value
from (select distinct market from t1) m cross join
t2 left join
t1
on t1.market = m.market and t1.date = t2.date;

T-SQL max date and min date between two date

First, thanks for your time and your help!
I have two tables:
Table 1
PersId name lastName city
---------------------------------------
1 John Smith Tirana
2 Leri Nice Tirana
3 Adam fortsan Tirana
Table 2
Id PersId salesDate
--------------------------------------------
1 1 2017-01-22 08:00:40 000
2 2 2017-01-22 09:00:00 000
3 1 2017-01-22 10:00:00 000
4 1 2017-01-22 20:00:00 000
5 3 2017-01-15 09:00:00 000
6 1 2017-01-21 09:00:00 000
7 1 2017-01-21 10:00:00 000
8 1 2017-01-21 18:55:00 000
I would like to see the first recent sales between two dates according to each city for each day I want to bring it empty if I do not have a sale
SalesDate > '2017-01-17 09:00:00 000'
and SalesDate < '2017-01-23 09:00:00 000'
Table 2, id = 5 because the record is not in the specified date range
If I wanted my results to look like
Id PersId MinSalesDate MaxSalesDate City
-----------------------------------------------------------------------------
1 1 2017-01-22 08:00:40 000 2017-01-22 20:00:00 000 Tirana
2 2 2017-01-22 09:00:00 000 null Tirana
3 3 null null Tirana
4 1 2017-01-21 09:00:00 000 2017-01-21 18:55:00 000 Tirana
You dont identify how to get ID in the result. You appear to just want Row_Number(). I will leave that out, but this should get you started. You may have to work out conversion issues in the data range check, and I havent checked the query for syntax errors, I will leave that to you.
Select T1.PersId, City
, Min(T2.salesDate) MinSalesDate
, Max(T2.salesDate) MaxSalesDate
From Table1 T1
Left Join Table2 T2
On T1.PersId = T2.PersId
And T2.salesDate Between '2017-01-17 09:00:00 000' And < '2017-01-23 09:00:00 000'
Group BY T1.PersId, T2.City
Try the following using row_number to get min and max sale dates:
SELECT
T2.Id, T1.PersId, T2.MIN_salesDate, T2.MAX_salesDate, T1.City
FROM Table1 T1
LEFT JOIN
(
SELECT MIN(Id) as Id, PersId, MIN(salesDate) as MIN_salesDate, MAX(salesDate) as MAX_salesDate
FROM
(
SELECT
*
,ROW_NUMBER() OVER (PARTITION BY PersId ORDER BY salesDate ASC) as RNKMIN
,ROW_NUMBER() OVER (PARTITION BY PersId ORDER BY salesDate DESC) as RNKMAX
FROM Table2 T2
WHERE salesDate Between '2017-01-17 09:00:00 000' And '2017-01-23 09:00:00 000'
) temp
WHERE RNKMIN = 1 or RNKMAX = 1
GROUP BY PersId
) T2
on T1.PersId = T2.PersId

Select all user that have a specific date and have been recorded only one time

I have this table.
My Sql table in (SQL Fiddle)
ID Date Value
___ ____ _____
3241 01/01/00 15456
3241 9/17/12 5
3241 9/16/12 100
3241 9/15/12 20
4355 01/01/00 01
4355 9/16/12 12
4355 9/15/12 132
4355 9/14/12 4
1001 01/01/00 456
1001 9/16/12 125
5555 01/01/00 01
1234 01/01/00 01
1234 9/16/12 45
2236 01/01/00 879
2236 9/15/12 128
2236 9/14/12 323
2002 01/01/00 567
I would like, to select all the record that have 01-01-00 as date and have been showed only one time.
The result that i'm trying to have is like the table below.
ID Date Value
___ ____ _____
5555 01/01/00 01
2002 01/01/00 567
I tried to use HAVING clause but because of the GROUP BY, the result is wrong because one of my select has more than one record which isn't good for my case.
My Wrong Attempt:
SELECT * FROM
(SELECT *
FROM table1
GROUP BY id, date, value
HAVING count(Id)=1) t1
WHERE date='01-01-00'
Query Result (SQL Fiddle)
I would use:
select id, max(date) as date, max(value) as value
from t1
group by id
having max(date) = '01-01-00' and count(*) = 1;
A somewhat faster method might be:
select t1.*
from t1
where date = '01-01-00' and
not exists (select 1 from t1 tt1 where tt1.id = t1.id and tt1.date <> '01-01-00');
This can take advantage of index on t1(date) and t1(id, date).
Use IN
SELECT *
FROM table1
WHERE id IN (
SELECT id
FROM table1
GROUP BY id
HAVING count(Id)=1
) and date='01-01-00'
I just didn't notice that i make a error in my group by instead of making only the ID, I put all the columns
SELECT * FROM
(SELECT *
FROM Table1
GROUP BY `ID`
HAVING count(`ID`)=1) t1
WHERE `Date`='2000-01-01 00:00:00'
However for my problem, I take this solution from Gordon Linoff because it's seems better for me.
PS:I have 2 million records.
Change your query as
SELECT *
FROM
(SELECT *
FROM table1
GROUP BY id
HAVING count(id)=1) t1
WHERE t1.date='01-01-00'