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;
Related
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
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);
There are two tables.
In the first I have columns:
id - a person
time - the time of receiving the bonus (timestamp)
money - size of bonus
And the second:
id
time - time of getting a rank (timestamp)
range - military rank (int)
The task is to withdraw the amount and number of bonuses received by people in the rank of captain (range = 7) with aggregation by day.
I have no ideas how to do a table with this data. I can summarize data by all days such as
SELECT DISTINCTROW Payment.user_id AS user_id, Sum(IIf(IsNull(Payment.money),0,Payment.money)) AS [Sum - money], Count(Payment.money) AS [Count - Payment], Format(Payment.time, "Short Date") as day
FROM Payment
GROUP BY Payment.user_id, Format (Payment.time, "Short Date")
Having ((Count(Payment.money) > 0));
Can you help me with second part and summarize them? thanks
For example: first table (Payment):
user_id time money
a 01.01.10 00:00:00 15,00
a 01.01.10 10:00:00 2,00
a 03.01.10 00:00:00 3,00
c 04.01.10 00:00:00 4,00
c 04.01.10 00:05:00 5,00
d 06.01.10 00:00:00 6,00
e 07.01.10 00:00:00 7,00
e 08.01.10 00:00:00 8,00
The second one:
user_id time range
a 01.01.10 00:00:00 6
a 01.01.10 09:00:00 7
a 04.01.10 00:00:00 8
b 04.01.10 00:00:00 4
c 04.01.10 00:05:00 7
d 06.01.10 00:00:00 5
e 07.01.10 00:00:00 6
f 08.01.10 00:00:00 6
g 08.01.10 00:00:00 7
I expected:
user_id time sum
a 01.01.10 2
a 03.01.10 3
c 04.01.10 5
Here is one possible method using joins:
select t1.user_id, datevalue(p.time) as [time], sum(p.money) as [sum]
from
(
(select t.user_id, t.time from rank t where t.range = 7) t1
inner join payment p on t1.user_id = p.user_id
)
left join
(select t.user_id, t.time from rank t where t.range > 7) t2 on p.user_id = t2.user_id
where
p.time >= t1.time and (t2.user_id is null or p.time < t2.time)
group by
t1.user_id, datevalue(p.time)
I have assumed that your second table is called rank (this was not stated in your question).
Here, the subquery t1 obtains the set of users with range = 7 (captain), and the subquery t2 obtains the set of users with range > 7. I then select all records with a payment date greater than or equal to the date of promotion to captain, but less than any subsequent promotion (if it exists).
This yields the following result:
+---------+------------+------+
| user_id | time | sum |
+---------+------------+------+
| a | 01/01/2010 | 2.00 |
| a | 03/01/2010 | 3.00 |
| c | 04/01/2010 | 5.00 |
+---------+------------+------+
Unless I have misunderstood, I would argue that your expected result is incorrect as the payment below occurs before user_id = c achieved the rank of captain:
c 04.01.10 00:00:00 4,00
c 04.01.10 00:05:00 7
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)
)
I want to join two tables based on timestamp, the problem is that both tables didn't had the exact same timestamp so i want to join them using a near timestamp using a 5 minute interval.
This query needs to be done using 2 Common table expressions, each common table expression needs to get the timestamps and group them by AVG so they can match
Freezer | Timestamp | Temperature_1
1 2018-04-25 09:45:00 10
1 2018-04-25 09:50:00 11
1 2018-04-25 09:55:00 11
Freezer | Timestamp | Temperature_2
1 2018-04-25 09:46:00 15
1 2018-04-25 09:52:00 13
1 2018-04-25 09:59:00 12
My desired result would be:
Freezer | Timestamp | Temperature_1 | Temperature_2
1 2018-04-25 09:45:00 10 15
1 2018-04-25 09:50:00 11 13
1 2018-04-25 09:55:00 11 12
The current query that i'm working on is:
WITH Temperatures_1 (
SELECT Freezer, Temperature_1, Timestamp
FROM TABLE_A
),
WITH Temperatures_2 (
SELECT Freezer, Temperature_2, Timestamp
FROM TABLE_B
)
SELECT A.Freezer, A.Timestamp, Temperature_1, Temperature_2
FROM Temperatures_1 as A
RIGHT JOIN Temperatures_2 as B
ON A.FREEZER = B.FREEZER
WHERE A.Timestamp = B.Timestamp
You should may want to modify your join criteria instead of filtering the output. Use BETWEEN to bracket your join value on the timestamps. I chose +/- 150 seconds because that's half of 2-1/2 minutes to either side (5-minute range to match). You may need something different.
;WITH Temperatures_1 (
SELECT Freezer, Temperature_1, Timestamp
FROM TABLE_A
),
WITH Temperatures_2 (
SELECT Freezer, Temperature_2, Timestamp
FROM TABLE_B
)
SELECT A.Freezer, A.Timestamp, Temperature_1, Temperature_2
FROM Temperatures_1 as A
RIGHT JOIN Temperatures_2 as B
ON A.FREEZER = B.FREEZER
AND A.Timestamp BETWEEN (DATEADD(SECOND, -150, B.Timestamp)
AND (DATEADD(SECOND, 150, B.Timestamp)
You should change the key of join two table by adding the timestamp. The timestamp you should need to approximate the datetime on both side tables A and B tables.
First you should check if the value of the left table (A) datetime is under 2.5 minutes then approximate to the near 5 min. If it is greater the approximate to the next 5 minutes. The same thing you should do on the right table (B). Or you can do this on the CTE and the right join remains the same as your query.