Merging old table with new table with different structure - sql

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

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

Identify if date is the last date for any given group?

I have a table that is structured like the below - this contains details about all customer subscriptions and when they start/end.
SubKey
CustomerID
Status
StartDate
EndDate
29333
102
7
01 jan 2013
1 Jan 2014
29334
102
6
7 Jun 2013
15 Jun 2022
29335
144
6
10 jun 2021
17 jun 2022
29336
144
2
8 oct 2023
10 oct 2025
I am trying to add an indicator flag to this table (either "yes" or "no") which shows me by each row, if when the [EndDate] of the SubKey is the last one for that CustomerID. So for the above example..
SubKey
CustomerID
Status
StartDate
EndDate
IsLast
29333
102
7
01 jan 2013
1 Jan 2014
No
29334
102
6
7 Jun 2013
15 Jun 2022
Yes
29335
144
6
10 jun 2021
17 jun 2022
Yes
29336
144
2
8 oct 2023
10 oct 2025
Yes
The flag is set to No for the first row, because on 1 Jan 2014, customerID 102 had another SubKey (29334) still active at the time (which didn't end until 15 jun 2022)
The rest of the rows are set to "Yes" because these were the last active subscriptions per CustomerID.
I have been reading about the LAG function which may be able to help. I am just not sure how to make it fit in this scenario.
Probably the easiest method would to use exists with a correlation. Can you try the following for your desired results for excluding rows without an overlap:
select *,
case when exists (
select * from t t2
where t2.customerId = t.customerId
and t2.enddate > t.enddate
and t2.startDate < t.Enddate
) then 'No' else 'Yes' end as IsLast
from t;

multiple sub-conditions in WHERE clause SQL

I have the following example of a table from which I want all rows where Year is '2016' and '2017' but want to exclude CustID 'AB17' and 'AB18' from Year '2017'. In total I should get 12 rows. See this fiddle
Example:
SQL:
SELECT * FROM testing
WHERE Year In ('2016','2017')
AND (CustID NOT In ('AB17','AB18') AND Year = '2017');
Table:
Year CustID Revenue
2016 AB12 10
2016 AB13 11
2016 AB14 12
2016 AB15 13
2016 AB16 14
2016 AB17 15
2016 AB18 16
2017 AB12 10
2017 AB13 11
2017 AB14 12
2017 AB15 13
2017 AB16 14
2017 AB17 15
2017 AB18 16
2018 AB12 17
2018 AB13 18
2018 AB14 19
2018 AB15 20
2018 AB16 21
2018 AB17 22
2018 AB18 23
Any suggestions?
This should work:
WHERE
Year = '2016'
OR (Year = '2017' AND CustID NOT In ('AB17','AB18'))
A pretty direct translation of:
Year is '2016' and '2017' but want to exclude CustID 'AB17' and 'AB18' from Year '2017'.
is:
where year in (2016, 2017) and
not (year = 2017 and custID in ('AB17', 'AB18'))

Finding repeat rate using sql

I have a table mentioned below:
If X customers had made the purchase in the month of Jan, how many of them made them in Feb too i.e Y. (Repeat Rate: Y/X*100)
customer_no month
---------------------
1 jan
2 jan
3 jan
4 jan
11 jan
1 feb
2 feb
3 feb
9 feb
10 feb
Output:
Repeat_Rate
60%
i would do it like:
SELECT CAST(COUNT(yourtable_feb.customer_no) as FLOAT)
/ CAST(COUNT(yourtable_jan.customer_no) AS FLOAT) AS Repeating_Rate
FROM yourtable yourtable_jan
LEFT JOIN yourtable yourtable_feb
ON yourtable_jan.customer_no = yourtable_feb.customer_no
AND yourtable_feb.mymonth = 'feb'
WHERE yourtable_jan.mymonth = 'jan'
here a rextester, if you'd like to retest my query:
http://rextester.com/ESO11614

How to calculate Rank SQL query

HI, I have the following table which save agent ranking on daily basis on basis of tickets status.
No. **Agent Name** **Incidents** **workorder** **Rank** **TimeStamp**
1 cedric 200 29 1 21 Jan 2011
2 poul 100 10 2 21 Jan 2011
3 dan 200 20 1 21 Jan 2011
4 cedric 100 19 2 22 Jan 2011
5 poul 200 26 1 22 Jan 2011
6 dan 150 20 2 22 Jan 2011
Now i need query which fetch ranking between two dates means if i select date between 21 jan 2011 to 22 jan 2011 then query return me agents average ranking between these two dates of agent not return the agent ranking details on date wise. I need single name of agent with his ranking.
Regards,
Iftikhar hashmi
Try
SELECT [Agent Name], AVG(RANK) FROM MY_TABLE WHERE [TimeStamp] BETWEEN DATE1 AND DATE2
GROUP BY [Agent Name]
(Update)
Thanks to Martin which reminded me I need to cast RANK.
SELECT [Agent Name], AVG(CAST(RANK AS FLOAT)) FROM MY_TABLE WHERE [TimeStamp] BETWEEN DATE1 AND DATE2
GROUP BY [Agent Name]