SQL Server: combine only dates with no reference - sql

I have a data such as
Table 1: (after converting data into the format I need with the below query later in this question after the left join)
Initially has details of tickets such as date, ticket number, ticket type.
Monthyear Premiumold Silverold
-----------------------------------
Jan 2019 233 156
Feb 2019 344 258
Mar 2019 222 298
Table 2: which I predicted and pushed from a different source in the same format
Monthyear Premium silver
----------------------------
Apr 2019 284 312
May 2019 267 344
Jun 2019 223 356
Jul 2019 244 367
Aug 2019 234 373
I want to get this data to be in a format such as:
Monthyear Premiumold Silverold Premium silver
---------------------------------------------------------
Jan2019 233 156 NULL NULL
Feb 2019 344 258 NULL NULL
Mar 2019 222 298 NULL NULL
Apr 2019 NULL NULL 284 312
May 2019 NULL NULL 267 344
Jun 2019 NULL NULL 223 356
Jul 2019 NULL NULL 244 367
Aug 2019 NULL NULL 234 373
which basically puts the months together and leaves out NULL in wherever data isn't present for.
I have tried:
select *
from
((select Monthyear, Premium, Silver
from [dbo].[Predicted]) c
left join
(select
case when (tickettype = 'Premium')
then count(number)
end as Premiumold,
case when (tickettype = 'Silver')
then count(number)
end as Silverold,
concat(convert(char(3), a.date, 0), ' ', year(a.date)) as Monthyear
from
openquery(SNOW, 'select number,date, ticket_type from ticketdata
where date between ''2019-01-01 00:00:00'' and ''2019-02-28 23:59:59''')a
group by concat(convert(char(3), a.sys_created_on, 0),' ',year(a.date)),tickettype) as b
on c.Monthyear = b.Monthyear)
This obviously isn't returning what I want.
Please help me with this.
Thanks!

Try this.
select ISNULL(a.monthyear,b.monthyear),a.Premiumold,silverold,Premium,silver from Table1 a
full join Table2 b on a.monthyear=b.MonthYear

use union all
select Monthyear,Premiumold,Silverold, null as Premium, null as silver
from tabl1
union all
select Monthyear,null,null,Premium,silver from tabl2

Related

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;

How do I select / identify a row based on criteria in a different row in SQL

I've never posted on here before but, I am really stumped on this and looking for any assistance I get! I am not the best SQL code writer and I do not understand every concept but I am quick learner. So, I am not sure this is best way to accomplish my goal and if there is a more efficient way to complete this, I would be open to learning. I appreciate any help that can be provided.
Task:
I am attempting to write a SQL code that will help me place a number under the "Grab" column that allows me to exclude other rows out that are not needed.
Issue:
Pricing has a timeframe when it is applicable. The [PriceBookTable] captures the time frame range for each price book that is listed. However, as time goes on, some price books become outdated and do not need to be reviewed.
Based on today's date, I am trying to identify the previous version price book as well as the next version (if there is one).
Table Used: [PriceBookTable]
ID
Description
CategoryID
ParentID
StartDate
EndDate
412
56 MSRP
56
NULL
NULL
NULL
413
3 MSRP
3
NULL
NULL
NULL
414
61 MSRP
61
NULL
NULL
NULL
415
63 MSRP
63
NULL
NULL
NULL
419
58 MSRP
58
NULL
NULL
NULL
420
62 MSRP
62
NULL
NULL
NULL
430
67 MSRP
67
NULL
NULL
NULL
431
68 MSRP
68
NULL
NULL
NULL
505
2020 Version 1
56
412
2020-08-31
2020-12-31
537
2021 Version 1
56
412
2021-01-01
2021-03-31
586
2021 Version 2
56
412
2021-04-01
2021-04-13
622
2021 Version 3
56
412
2021-04-14
2021-07-31
688
2021 Version 4
56
412
2021-08-01
2021-12-31
Current Code:
USE [Database]
DECLARE #PriceBookID AS VARCHAR(10)
SET #PriceBookID = '412' --Parent Price Book ID
SELECT A.*,
[Grab] = CASE WHEN A.ParentID IS NULL AND A.StartDate IS NULL AND A.EndDate IS NULL THEN 1 -- Always needs to be #1
WHEN CAST(GETDATE() AS DATE) BETWEEN A.StartDate AND A.EndDate THEN 3 --Currently Active Price Book based on Today's Date
ELSE NULL END
FROM( SELECT ID,
ParentID,
[PriceBookDescription] = Description,
StartDate,
EndDate,
[ActivePriceBook] = CASE WHEN CAST(GETDATE() AS DATE) BETWEEN StartDate AND EndDate THEN 'Active' ELSE NULL END,
[PBOrder] = ROW_NUMBER() OVER (ORDER BY ID ASC)
FROM [PriceBookTable]
WHERE 1=1 AND ID IN (#PriceBookID) OR ParentID IN (#PriceBookID)) A
Current Output:
ID
ParentID
PriceBookDescription
StartDate
EndDate
ActivePriceBook
PBOrder
Grab
412
Null
MSRP
NULL
NULL
NULL
1
1
505
412
2020 Version 1
2020-08-31
2020-12-31
NULL
2
NULL
537
412
2021 Version 1
2021-01-01
2021-03-31
NULL
3
NULL
586
412
2021 Version 2
2021-04-01
2021-04-13
NULL
4
NULL
622
412
2021 Version 3
2021-04-14
2021-07-31
Active
5
3
688
412
2021 Version 4
2021-08-01
2021-12-31
NULL
6
NULL
Notes:
I originally was hoping that the "PBOrder" column would be useful for me but, as time goes on the list becomes bigger as more price books are created and, for example, row #4 [ID 586] will not always be relevant.
I would have just placed a "WHERE ID IN ('412','586','622','688')" statement but the ID's change based on different categories (not shown). So, I am stuck to the date range.
Desired Output:
ID
ParentID
PriceBookDescription
StartDate
EndDate
ActivePriceBook
PBOrder
Grab
412
Null
MSRP
NULL
NULL
NULL
1
1
586
412
2021 Version 2
2021-04-01
2021-04-13
NULL
4
2
622
412
2021 Version 3
2021-04-14
2021-07-31
Active
5
3
688
412
2021 Version 4
2021-08-01
2021-12-31
NULL
6
4
I hope this makes sense and please let me know if you have any questions regarding this.
Thank you again for any help!
Took me awhile to understand what you wanted, but after figuring it out I was able to address what you need. Basically, you want:
To identify a single active record within a category based on the current date.
Then get the adjacent inactive records, with respect to time, that share a parent record.
Then get the record for the parent category and include it in the result set.
The 'pbOrder' and 'grab' columns seem to be throughputs to achieve this goal. You don't need them in the output.
If this is all correct, then you can delegate your identification of an active record to a cross apply calculation, and then use lead and lag in addition to the raw result to identify the active record as well as the adjacent ones in time.
declare #PriceBookID int = 412; -- why varchar, I would use int
with rowsToGrab as (
select pbt.*,
ap.activePriceBook,
grab =
case
when pbt.ParentID is null then 1
when lead(ap.ActivePriceBook) over(order by pbt.startDate) is not null then 1
when lag(ap.ActivePriceBook) over(order by pbt.startDate) is not null then 1
when ap.ActivePriceBook is not null then 1
end
from #PriceBookTable pbt
cross apply (select ActivePriceBook =
case
when cast(getdate() as date) between startdate and enddate then 'Active'
end
) ap
where #PriceBookID in (ID, ParentID)
)
select id, ParentID, description as PriceBookDescription, StartDate, EndDate, ActivePriceBook
from rowsToGrab
where grab is not null
order by id, StartDate
This produces:
id
ParentID
PriceBookDescription
StartDate
EndDate
ActivePriceBook
412
56 MSRP
586
412
2021 Version 2
2021-04-01
2021-04-13
622
412
2021 Version 3
2021-04-14
2021-07-31
Active
688
412
2021 Version 4
2021-08-01
2021-12-31

Hive LAG function - year over year change - to get previous value even if there is no current vaue

I am calculating year over year change and below is the query in hive
select Name,
Year,
Month,
ID,
value as Current,
LAG(value,1,0) OVER(PARTITION BY name,month,id ORDER BY year ASC) as Previous,
value - LAG(value,1,0) OVER(PARTITION BY name,month,id ORDER BY year ASC) as Change
Current Result
Name Year Month ID Current Previous Change
A 2015 1 8320 944 0 944
O 2015 1 8320 153 0 153
O 2016 1 8320 133.92 153 -19.08
B 2015 1 8320 572 0 572
C 2016 1 8320 126 0 126
There are 3 cases for the year 2016
Name O - Has both values for 2016 and 2015 and I get difference
Name C - Has value only in 2016 and I get the difference keeping 2015 as 0
Name A and B - Has values only in 2015 and not in 2016 - So I need to get two entries with change as -944 and -572 for A and B respectively.
My expected result is:
Name Year Month ID Current Previous Change
A 2015 1 8320 944 0 944
A 2016 1 8320 0 944 -944
O 2015 1 8320 153 0 153
O 2016 1 8320 133.92 153 -19.08
B 2015 1 8320 572 0 572
B 2016 1 8320 0 572 -572
C 2016 1 8320 126 0 126
Please guide me how to get the previous year values, even if there are no current year values.Thanks for the help in advance.

How to get data exist for more than one instance which belongs to the same key?

If i have table structure like that:
req_serial req_year emp_num name
15 2014 673 Jo
16 2015 673 Jo
17 2014 785 Noha
17 2015 785 Noha
17 2014 634 Reem
17 2015 634 Reem
18 2014 358 Moh
18 2014 34 Amr
18 2015 34 Amr
How to get the following result :
17
18
I want to get the req_serial if the same employee exist in more than one req_year belongs to the same req_serial? .How to do that?
A simple GROUP BY should do it:
SELECT DISTINCT req_serial
FROM mytable
GROUP BY req_serial, name
HAVING COUNT(DISTINCT req_year) > 1
If the same pair of values for req_serial, name spans over more than one year, then the above query returns this exact pair. We only need req_serial, this is why DISTINCT req_serial is used in the SELECT clause.
Demo here

SQL/DB2 - How can I choose which rows to use aggregate functions on, and which to ignore?

I'm sure this is a simple problem for SQL/DB2 gurus, but I'm still a novice and I can't think my way through this.
I have a table with four columns: Amount, ID1, ID2, and Date. Here's a sample of the data:
Amount ID1 ID2 Date
3,220 127 149 Dec 1
3,220 127 424 Dec 1
637 130 149 Dec 1
637 130 424 Dec 1
2232 161 149 Dec 1
2232 161 424 Dec 1
1221 372 149 Dec 1
1221 372 424 Dec 1
1221 372 149 Jun 1
1221 372 424 Jun 1
554 54 149 Dec 1
554 54 424 Dec 1
554 54 149 Jun 1
554 54 424 Jun 1
So, what I'm trying to do is get a SUM() of the Amounts, for each ID1, ignoring ID2, and only for the currentmost Date. It's the date that's causing me the trouble. The closest I can get it is this:
Sum Amounts
6440
1274
4464
4884
1108
When what I want is this:
Sum Amounts
6440
1274
4464
2442
2216
What I really want is for the last two numbers to only SUM() the amounts for Jun 1, and ignore Dec 1. To basically take the currentmost dates.
This should work for you:
SELECT id1, SUM(amount)
FROM table1 a
WHERE date = (SELECT MAX(date)
FROM table1 b
WHERE a.id1 = b.id1
AND a.id2 = b.id2)
GROUP BY id1