Populate data from One table to another with out matching Key - sql

Can any one tell me how to do this....
Table 1 Table 2
Cat_ID Cat_Name Term_ID Term_Name
1 ab 1986 January 2013
2 cd 1987 February 2013
3 ef 1988 March 2013
4 gh
I want the Output as :
Table 3
Term_ID Term_Name CAT_ID CAT_Name
1986 January 2013 1 ab
1986 January 2013 2 cd
1986 January 2013 3 ef
1986 January 2013 4 gh
1987 February 2013 1 ab
1987 February 2013 2 cd
1987 February 2013 3 ef
1987 February 2013 4 gh
1988 March 2013 1 ab
1988 March 2013 2 cd
1988 March 2013 3 ef
1988 March 2013 4 gh
I have to write it as a SQL query.

You can use a CROSS JOIN to get the Cartesian result that you want:
select t2.term_id,
t2.term_name,
t1.cat_id,
t1.cat_name
from table1 t1
cross join table2 t2
See SQL Fiddle with Demo. Once you have the result, then you can INSERT the data into table3:
insert into table3 (term_id, term_name, cat_id, cat_name)
select t2.term_id,
t2.term_name,
t1.cat_id,
t1.cat_name
from table1 t1
cross join table2 t2

Related

Count records and group by different field while showing max value

id
year
1
2014
10
2015
10
2019
102
2015
102
2019
104
2015
104
2017
104
2019
104
2021
The output I want in postgres is below. The max year is populated based on the id and the count should also count based on id. If id = 10 then it should show the max date within id 10 and also count how many records have the id as 10.
id
year
max year
count
1
2014
2014
1
10
2015
2017
2
10
2017
2017
2
102
2015
2019
2
102
2019
2019
2
104
2015
2021
4
104
2017
2021
4
104
2019
2021
4
104
2021
2021
4
SELECT aa.id,
aa.year,
aa.max_year,
count(aa.id)
from (SELECT id,MAX(year) AS year FROM table
GROUP BY id) aa
FULL JOIN table2 b ON aa.id = b.id
You can use window functions:
select id,
year,
max(year) over (partition by id) as max_year,
count(*) over (partition by id)
from the_table

Sort SQL by value

I have data like this:
Customer ID
Name
Type
Last Submit
1
Patricio
C
January 2022
2
Dale
A
June 2022
3
Yvonne
C
July 2022
4
Pawe
C
JUne 2022
5
Sergio
B
August 2022
6
Roland
C
August 2022
7
Georg
D
November 2022
8
Catherine
D
October 2022
9
Pascale
E
October 2022
10
Irene
A
November 2022
How to sort type A out of the queue first like A,B,C,D,E,F, then the last submit is at the top.
The example output:
Customer ID
Name
Type
Last Submit
10
Irene
A
November 202[![enter image description here][1]][1]2
1
Dale
A
June 2022
5
Sergio
B
August 2022
6
Roland
C
August 2022
3
Yvonne
C
July 2022
4
Pawe
C
June 2022
1
Patricio
C
January 2022
7
Georg
D
November 2022
8
Catherine
D
October 2022
9
Pascale
E
October 2022
So basically you want to sort by 2 different columns, this is detailed in this other answer: SQL multiple column ordering
In your example you would do
ORDER BY type, last_submit
Hi you can use simple order by in postgresql
like this
SELECT
*
FROM
table (your table name)
ORDER BY
type ASC, last_submit DESC;
In this case, you need to sort your query using the two columns in order.
Add this part to the end of your query.
ORDER BY type, last_submit DESC;
Check out this question "SQL multiple column ordering"

Using SQL, when there are multiple columns with dates. how can I determine and return a row where the date is between the other rows?

I am building a table for a data warehouse that needs to have a row for each change that occurs. The issue is that there are sometimes changes that occur in the subgroups and I can't figure out how to show those changes.
For example, I have the following table:
RowNumber
Code
CorrectedProductYear
ProductYear
Product
CategoryYear
Category
PartYear
Parts
KeepRow
1
ABC
2012
2012
Sport Car
1995
Auto
1980
Wheels
N
2
ABC
2012
2012
Sport Car
1996
Cars
1980
Wheels
N
3
ABC
2012
2012
Sport Car
1998
Transport
1980
Wheels
Y
4
ABC
2014
2014
Sedan
1995
Auto
1980
Wheels
N
5
ABC
2014
2014
Sedan
1996
Cars
1980
Wheels
N
6
ABC
2014
2014
Sedan
1998
Transport
1980
Wheels
Y
7
ABC
2018
2018
Luxury Car
1995
Auto
1980
Wheels
N
8
ABC
2018
2018
Luxury Car
1996
Cars
1980
Wheels
N
9
ABC
2018
2018
Luxury Car
1998
Transport
1980
Wheels
N
10
ABC
2016
2018
Sedan
2016
Vehicle
1980
Wheels
Y
11
ABC
2018
2018
Luxury Car
2017
Motorcar
1980
Wheels
Y
12
ABC
2018
2018
Luxury Car
2017
Motorcar
1980
Wheels
N
13
ABC
2019
2018
Luxury Car
2017
Motorcar
2019
Fancy Wheels
Y
14
ABC
2020
2020
Super Luxury Car
2017
Motorcar
2019
Fancy Wheels
N
15
ABC
2020
2020
Super Luxury Car
2017
Motorcar
2019
Fancy Wheels
Y
I marked the KeepRow with a 'Y' to show what the find result should look like. It should be this:
RowNumber
Code
CorrectedProductYear
Product
CategoryYear
Category
PartYear
Parts
KeepRow
3
ABC
2012
Sport Car
1998
Transport
1980
Wheels
Y
6
ABC
2014
Sedan
1998
Transport
1980
Wheels
Y
10
ABC
2016
Sedan
2016
Vehicle
1980
Wheels
Y
11
ABC
2018
Luxury Car
2017
Motorcar
1980
Wheels
Y
13
ABC
2019
Luxury Car
2017
Motorcar
2019
Fancy Wheels
Y
15
ABC
2020
Super Luxury Car
2017
Motorcar
2019
Fancy Wheels
Y
In this table the ProductYear is the "main" year. When the subgroupings (Category and Parts) have a change in their description/year, that needs to be captured in the ProductYear. This occurs in:
Row 10 - where the Category changes to Vehicle in 2016, so it is between the ProductYear of 2014 Sedan and 2018 Luxury Car. Additionally, the Product needs to revert back to Sedan because Luxury Car had not yet been produced.
Row 13 - Parts changes to Fancy Wheels in 2019 which is between the ProductYear of 2018 and 2020.
I know that I can do an Max Effective Date query to only pull the most recent CategoryYear and PartYear, but then I miss the changes that might occur between the ProductYear.
I've tried different variations of LAG and LEAD and well as LAST_VALUE and some of the other Window functions, but I'm at stuck and can't figure this one out.
I also think that this might not be able to be completed with just SQL. I do have the ability to do some SSIS if that is a better way to proceed.
Any help would be enormously appreciated!
Thank you.
I think this is something like what you are looking for. I had to split it into two queries as you are filtering once for CategoryYear and then again for PartYear. This might help you get on the right path:
SELECT RowNumber,Code,CorrectedProductYear,ProductYear,Product,CategoryYear,Category,PartYear,Parts
FROM
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY Product order by ProductYear) RN,
LAG(ProductYear,1) OVER(order by ProductYear) LastProdYear,
LEAD(ProductYear,1) OVER(order by ProductYear) NextProdYear,
LAG(Category,1) OVER(Order by Product,ProductYear) LastCategory
FROM Products
) T
WHERE CategoryYear > LastProdYear and CategoryYear < NextProdYear
and KeepRow = 'Y' and Category <> LastCategory and RN > 1
UNION ALL
SELECT RowNumber,Code,CorrectedProductYear,ProductYear,Product,CategoryYear,Category,PartYear,Parts
FROM
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY Product order by ProductYear) RN,
LAG(ProductYear,1) OVER(order by ProductYear) LastProdYear,
LEAD(ProductYear,1) OVER(order by ProductYear) NextProdYear,
LAG(Parts,1) OVER(Order by Product,ProductYear) LastParts
FROM Products
) T
WHERE PartYear > LastProdYear and PartYear < NextProdYear
and KeepRow = 'Y' and Parts <> LastParts and RN > 1

Merging old table with new table with different structure

I am using SQL Server 2012. I have two tables which I need to 'merge'. The two tables are called tblOld and tblNew.
tblOld has data from say 2012 to 2013
tblNew has data from 2013 onwards and has a different structure
The dates do not overlap between the tables.
Simple example of the tables:
Old table
t_date region sub_region sales
------------------------------------------
1 Jan 2012 US QR 2
1 Jan 2012 US NT 3
1 Jan 2012 EU QR 5
2 Jan 2012 US QR 4
2 Jan 2012 US NT 6
2 Jan 2012 EU QR 10
...
31 Dec 2013 US QR 8
31 Dec 2013 US NT 9
31 Dec 2013 EU QR 15
New table
t_date region sales
-----------------------------
1 Jan 2014 US 20
1 Jan 2014 EU 50
2 Jan 2014 US 40
2 Jan 2014 EU 100
...
31 Dec 2014 US 80
31 Dec 2014 EU 150
Result I'm looking for:
t_date US QR US NT EU
-------------------------------------
1 Jan 2012 2 3 5
2 Jan 2012 4 6 10
...
31 Dec 2013 8 9 15
1 Jan 2014 20 50
2 Jan 2014 40 100
...
31 Dec 2014 80 150
So I'm trying to create a query which will give me the results above although I'm not sure how to do this or if it can be done?
SELECT t_date,
SUM(CASE WHEN region='US' AND (sub_region='QR' OR sub_region IS NULL) THEN sales ELSE 0 END) 'US QR',
SUM(CASE WHEN region='US' AND sub_region='NT' THEN sales ELSE 0 END) 'US NT',
SUM(CASE WHEN region='EU' THEN sales ELSE 0 END) 'EU'
FROM (
SELECT t_date
,region
,sub_region
,sales
FROM tblOLD
UNION ALL
SELECT t_date
,region
,NULL
,sales
FROM tblNEW
) t
GROUP BY t_date
You are looking for a UNION of the two tables:
SELECT t_date
,region
,sales
,sub_region
FROM tblOLD
UNION ALL
SELECT t_date
,region
,NULL
,sales
FROM tblNEW

SQL Select rows based on date

I have a two tables (Table1 and Table2):
Table1
Date Name Other
2014-02-08 Alex 1
2014-06-15 Bob 1
Table2
Date Name Count
2014-02-07 Alex 1
2014-01-31 Alex 2
2014-02-09 Alex 4
2014-02-08 Alex 10
2014-02-10 Alex 0
2014-02-01 Alex 4
2014-01-08 Alex 5
2014-03-08 Alex 4
2014-06-01 Bob 22
2014-06-02 Bob 0
2014-06-10 Bob 9
2014-06-15 Bob 3
2014-06-16 Bob 3
2014-06-20 Bob 5
2014-06-14 Bob 18
2014-07-11 Bob 1
2014-08-15 Bob 2
I am having a difficult time constructing a query that accomplishes the following:
From Table1, run through each "Date" and "Name"
For a given "Date" and "Name" in Table1, go through Table2 and grab all rows that also have the same "Name" and that have dates that are 10 days before the "Date" (in Table1) and 5 days after "Date" (in Table1).
So, for Table1, "Alex" on "2014-02-08", I want to grab all rows in Table2 that also say "Alex" but whose date is between "2014-01-29" (10 days before 2014-02-08) and "2014-02-13" (5 days after 2014-02-08).
For "Bob" on "2014-06-15", I want to grab all rows in Table2 that also say "Bob" but whose date is between "2014-06-05" (10 days before 2014-06-15) and "2014-06-20" (5 days after 2014-06-15).
The expected output is:
Date Name Count
2014-02-07 Alex 1
2014-01-31 Alex 2
2014-02-09 Alex 4
2014-02-08 Alex 10
2014-02-10 Alex 0
2014-02-01 Alex 4
2014-06-10 Bob 9
2014-06-15 Bob 3
2014-06-16 Bob 3
2014-06-20 Bob 5
2014-06-14 Bob 18
In my real work, the number of rows in Table1 is much larger and the number of days I'd like to grab before/after the reference date can vary.
I think you can do something like this:
select t2.*
from table1 t2
where exists (select 1
from table1 t1
where t1.name = t2.name and t1.date >= t2.date - 'interval 10 day' and
t1.date <= t2.date + 'interval 10 day'
);
See:
http://sqlfiddle.com/#!4/82e1e/10
Assuming Oracle, but you get the picture:-). You would need to format the date in the results. That is left for your perusal.
In case, the above link cannot be opened, the sql is:
select t2.*
from
table2 t2, table1 t1
where
t1.name = t2.name
and t2.date1 > t1.date1 -10
and t2.date1 <= t1.date1 +5;
The result is:
DATE1 NAME COUNT
February, 07 2014 00:00:00+0000 Alex 1
January, 31 2014 00:00:00+0000 Alex 2
February, 09 2014 00:00:00+0000 Alex 4
February, 08 2014 00:00:00+0000 Alex 10
February, 10 2014 00:00:00+0000 Alex 0
February, 01 2014 00:00:00+0000 Alex 4
June, 10 2014 00:00:00+0000 Bob 9
June, 15 2014 00:00:00+0000 Bob 3
June, 16 2014 00:00:00+0000 Bob 3
June, 20 2014 00:00:00+0000 Bob 5
June, 14 2014 00:00:00+0000 Bob 18