How To Merge Two Table into one output data - sql-server

I have two tables with similar information:
1st Table For Estimation Data :
EstChargeCode | EstAmount
------------- | -------------
CNFS0001 | 43,250,000.00
CNIH0001 | 0.00
CNIH0001 | 2,625,000.00
CNIP0001 | 4,500,000.00
CNIP0005 | 2,250,000.00
CNOH0001 | 20,484,690.00
CNOP0001 | 0.00
2nd Table for Actual Data :
ActChargeCode | ActAmount
------------- | -------------
CNFS0001 | 39,950,000.00
CNIH0001 | 1,300,000.00
CNIH0001 | 950,000.00
CNIH0001 | -950,000.00
CNIH0001 | 950,000.00
CNIP0001 | 4,500,000.00
CNIP0005 | 2,250,005.00
CNOH0001 | 20,484,690.00
CNOP0001 | 3,300,000.00
if using Union All to merge the table from above then the result like this
ChargeCode | EstAmount | ActAmount
---------- | ------------- | -------------
CNFS0001 | 43,250,000.00 | -------------
CNIH0001 | 0.00 | -------------
CNIH0001 | 2,625,000.00 | -------------
CNIP0001 | 4,500,000.00 | -------------
CNIP0005 | 2,250,000.00 | -------------
CNOH0001 | 20,484,690.00 | -------------
CNOP0001 | 0.00 | -------------
CNFS0001 | ------------- | 39,950,000.00
CNIH0001 | ------------- | 1,300,000.00
CNIH0001 | ------------- | 950,000.00
CNIH0001 | ------------- | -950,000.00
CNIH0001 | ------------- | 950,000.00
CNIP0001 | ------------- | 4,500,000.00
CNIP0005 | ------------- | 2,250,005.00
CNOH0001 | ------------- | 20,484,690.00
CNOP0001 | ------------- | 3,300,000.00
I need to group both data into single result data like this
ChargeCode | EstAmount | ActAmount
---------- | ------------- | -------------
CNFS0001 | 43,250,000.00 | 39,950,000.00
CNIH0001 | 0.00 | 1,300,000.00
CNIH0001 | 0.00 | 950,000.00
CNIH0001 | 0.00 | -950,000.00
CNIH0001 | 0.00 | 950,000.00
CNIH0001 | 2,625,000.00 | 0.00
CNIP0001 | 4,500,000.00 | 4,500,000.00
CNIP0005 | 2,250,000.00 | 2,250,005.00
CNOH0001 | 20,484,690.00 | 20,484,690.00
CNOP0001 | 0.00 | 3,300,000.00
I don't know how handle this out. Any help would be greatly appreciated!

you can use code like below
select isnull(EstChargeCode ,ActChargeCode ) as ChargeCode ,isnull(EstAmount,0) as
EstAmount , isnull(ActAmount,0) as ActAmount from Estimation full join Actual
on Estimation.EstChargeCode =Actual.ActChargeCode

select a.EstChargeCode as ChargeCode ,
a.EstAmount,
b.ActAmount
from Estimation_Data as a
LEFT JOIN Actual_Data as b
ON a.ActChargeCode =b.ActChargeCode

You use INNER JOIN like:
SELECT T1.EstChargeCode AS EstChargeCode,
T1.EstAmount AS EstAmount1,
T2.EstAmount AS EstAmount2
FROM Table1 T1 INNER JOIN Table2 T2 ON T1.EstChargeCode = T2.ActChargeCode;

You can use JOIN to achieve the result:
SELECT t2.ActAmount ChargeCode ,nvl(t1.EstAmount,0.0) EstAmount, nvl(t2.ActAmount,0.0) ActAmount
FROM <Estimation Data table> t1
RIGHT OUTER JOIN <Actual Data> t2 ON t1.EstChargeCode = t2.ActChargeCode ;
For more clarification, there is an explanation here:
What is the difference between "INNER JOIN" and "OUTER JOIN"?

Related

How can generate one record into two records and then insert them into the table?

I have PKT table in sql server with structure(PKT(pso, day, msch, mskh, tkc, tkdu, st, mskh1)) and an other table(dong_bo(pso, day, msch, mskh, tk, psn, psc)).
With each row in PKT, i need to generate it to two rows then insert them into dong_bo table.
For Example: PKT table.
| pso | day | msch | mskh | tkc | tkdu | st | mskh1 |
| --- | --- | ---- | ---- | --- | ---- | -- | ----- |
| PKHT000105-12-20 | 31/12/2020 | 03 | 0802345 | C1411 | N3311 | 20000 | 7101259|
dong_bo table:
pso
day
msch
mskh
tk
psn
psc
PKHT000105-12-20
31/12/2020
03
0802345
1411
0
20000
PKHT000105-12-20
31/12/2020
03
7101259
3311
20000
0
I need a statement to generate it in SQL server.
Basically you can use union all statement as approach:
insert into dong_bo
select pso, day, mskh, right(tkc, 4) tkc, 0 psn, st psc from PKT
union all
select pso, day, mskh1, right(tkdu, 4) tkc, st psn, 0 psc from PKT;
Check this SQL online
Result:
+==================+============+=========+======+=======+=======+
| pso | day | mskh | tkc | psn | psc |
+==================+============+=========+======+=======+=======+
| PKHT000105-12-20 | 31/12/2020 | 0802345 | 1411 | 0 | 20000 |
+------------------+------------+---------+------+-------+-------+
| PKHT000105-12-20 | 31/12/2020 | 7101259 | 3311 | 20000 | 0 |
+------------------+------------+---------+------+-------+-------+

Cumulative Count of NULL restarting at NOT NULL

I would like to add a column indicating the number invites a person received before they accepted by incrementally counting the number of null columns before a non-null while partitioning over the PERSON_ID and ordering by the INVITED_DATE.
My table has the following format:
| UNIQUE_ID | PERSON_ID | INVITED_DATE | ACCEPTED_DATE |
| 12345 | 567 | 12-01-18 | NULL |
| 12346 | 567 | 12-02-18 | NULL |
| 12347 | 567 | 12-03-18 | NULL |
| 12348 | 567 | 12-04-18 | 12-04-18 |
| 12349 | 567 | 12-05-18 | NULL |
| 12350 | 568 | 12-01-18 | NULL |
| 12351 | 568 | 12-02-18 | 12-02-18 |
The output should ideally look like the following:
| UNIQUE_ID | PERSON_ID | INVITED_DATE | ACCEPTED_DATE | INVITES_BEFORE_ACCEPT |
| 12345 | 567 | 12-01-18 | NULL | 1 |
| 12346 | 567 | 12-02-18 | NULL | 2 |
| 12347 | 567 | 12-03-18 | NULL | 3 |
| 12348 | 567 | 12-04-18 | 12-04-18 | 0 |
| 12349 | 567 | 12-05-18 | NULL | 1 |
| 12350 | 568 | 12-01-18 | NULL | 1 |
| 12351 | 568 | 12-02-18 | 12-02-18 | 0 |
So far I've tried a number iterations of ROW NUMBER with OVER and PARTITION but I've found it will need to be an OUTER APPLY. The following OUTER APPLY counts over the data but doesn't restart the count with a successful accept.
SELECT t.* , invites.INVITES_BEFORE_ACCEPT
FROM table t
OUTER APPLY (
SELECT COUNT(*) INVITES_BEFORE_ACCEPT
FROM table t2
WHERE t.PERSON_ID = t2.PERSON_ID and t.INVITED_DATE < t2.ACCEPTED_DATE
) invites
One way would be
WITH t
AS (SELECT *,
COUNT(ACCEPTED_DATE)
OVER (
PARTITION BY PERSON_ID
ORDER BY INVITED_DATE) AS Grp
FROM [table])
SELECT *,
SUM(CASE
WHEN ACCEPTED_DATE IS NULL
THEN 1
ELSE 0
END)
OVER (
PARTITION BY PERSON_ID, Grp
ORDER BY INVITED_DATE) AS INVITES_BEFORE_ACCEPT
FROM t
Demo

SQL Server add all rows where a condition is validate

I have a SQL Server database in which I need to add all the cost for a job family.
I have a table like this
Table : work
+-------+-----------+-----------+---------+
| wonum | cost1 | cost2 | wogroup |
+-------+-----------+-----------+---------+
| 1 | 30.12 | 157.14 | 1 |
| 2 | 110.10 | 0.00 | 1 |
| 3 | 12.67 | 45.45 | 1 |
| 4 | 0.00 | 0.00 | 4 |
| 5 | 400.00 | 11.54 | 4 |
+-------+-----------+-----------+---------+
I need to add cost1 and cost2 for all the row who have the same wogroup but only for the on where wonum = wogroup.
Like this
+-------+-----------+-----------+---------+---------+
| wonum | cost1 | cost2 | wogroup | total |
+-------+-----------+-----------+---------+---------+
| 1 | 30.12 | 157.14 | 1 | 355.48 |
| 2 | 110.10 | 0.00 | 1 | null |
| 3 | 12.67 | 45.45 | 1 | null |
| 4 | 0.00 | 0.00 | 4 | 411.54 |
| 5 | 400.00 | 11.54 | 4 | null |
+-------+-----------+-----------+---------+---------+
In a perfect world, the null value would be the sum of cost1 and cost2 for the row but I'm not sure if it is possible...
EDIT: I can only do a select, it is for a BiRT report
Since this can change with more wonum being added, I'd have this as a VIEW
declare #work table (wonum int , cost1 decimal (6,3), cost2 decimal (6,3) , wogroup int)
insert into #work
values
(1,30.12,157.14,1),
(2,110.10,0.00,1),
(3,12.67,45.45,1),
(4,0.00,0.00,4),
(5,400.00,11.54,4)
select
*,
total = case when wonum = min(wonum) over (partition by wogroup) then sum(cost1) over (partition by wogroup) + sum(cost2) over (partition by wogroup) end
from #work
RETURNS
+-------+-----------+-----------+---------+---------+
| wonum | cost1 | cost2 | wogroup | total |
+-------+-----------+-----------+---------+---------+
| 1 | 30.12 | 157.14 | 1 | 355.48 |
| 2 | 110.10 | 0.00 | 1 | null |
| 3 | 12.67 | 45.45 | 1 | null |
| 4 | 0.00 | 0.00 | 4 | 411.54 |
| 5 | 400.00 | 11.54 | 4 | null |
+-------+-----------+-----------+---------+---------+
YOUR QUERY
select
*,
total = case when wonum = min(wonum) over (partition by wogroup)
then sum(cost1) over (partition by wogroup) + sum(cost2) over (partition by wogroup)
else null
end
from work

Unpivoting multiple, repeated columns with multiple (denormalized) values

I have a table with multiple columns like this...
+-------+----------------+---------+---------+-----------+------------+-----------+-----------+------------+---------+-----------+------------+
| Name | Email | Address | Order1 | Shipping1 | Date1 | Order2 | Shipping2 | Date2 | Order3 | Shipping3 | Date3 |
+-------+----------------+---------+---------+-----------+------------+-----------+-----------+------------+---------+-----------+------------+
| John | john#abcd.com | 123 | Rock | 123 | 02/11/2017 | Computer | 123 | 07/11/2017 | Pen | 123 | 12/11/2017 |
| Jane | jane#abcd.com | 234 | Scissor | 234 | 03/11/2017 | Laptop | 234 | 08/11/2017 | Pencil | 234 | 13/11/2017 |
| Julie | julie#abcd.com | 345 | Paper | 345 | 04/11/2017 | Mouse | 345 | 09/11/2017 | Clips | 345 | 14/11/2017 |
| Jaden | jaden#abcd.com | 456 | Spock | 456 | 05/11/2017 | Screen | 456 | 10/11/2017 | Pins | 456 | 15/11/2017 |
| Jabba | jabba#abcd.com | 678 | Lizard | 678 | 06/11/2017 | Pen Drive | 678 | 11/11/2017 | Notepad | 678 | 16/11/2017 |
+-------+----------------+---------+---------+-----------+------------+-----------+-----------+------------+---------+-----------+------------+
And I want to unpivot the columns into rows like this in T-SQL...
+-------+----------------+---------+-----------+----------+------------+
| Name | Email | Address | Order | Shipping | Date |
+-------+----------------+---------+-----------+----------+------------+
| John | john#abcd.com | 123 | Rock | 123 | 02/11/2017 |
| John | john#abcd.com | 123 | Computer | 123 | 07/11/2017 |
| John | john#abcd.com | 123 | Pen | 123 | 12/11/2017 |
| Jane | jane#abcd.com | 234 | Scissor | 234 | 03/11/2017 |
| Jane | jane#abcd.com | 234 | Laptop | 234 | 08/11/2017 |
| Jane | jane#abcd.com | 234 | Pencil | 234 | 13/11/2017 |
| Julie | julie#abcd.com | 345 | Paper | 345 | 04/11/2017 |
| Julie | julie#abcd.com | 345 | Mouse | 345 | 09/11/2017 |
| Julie | julie#abcd.com | 345 | Clips | 345 | 14/11/2017 |
| Jaden | jaden#abcd.com | 456 | Spock | 456 | 05/11/2017 |
| Jaden | jaden#abcd.com | 456 | Screen | 456 | 10/11/2017 |
| Jaden | jaden#abcd.com | 456 | Pins | 456 | 15/11/2017 |
| Jabba | jabba#abcd.com | 678 | Lizard | 678 | 06/11/2017 |
| Jabba | jabba#abcd.com | 678 | Pen Drive | 678 | 11/11/2017 |
| Jabba | jabba#abcd.com | 678 | Notepad | 678 | 16/11/2017 |
+-------+----------------+---------+-----------+----------+------------+
I googled and checked other posts related to this but unable to get three values. :(
Appreciate the help!
You won't need to necessarily use UNPIVOT here at all.
You'll be able to UNION the three denormalized Orders back into a flattened output, like so:
SELECT name, Email, Address, Order1 AS Order, Shipping1 as Shipping, Date1 AS Date
FROM Table1
UNION ALL
SELECT name, Email, Address, Order2, Shipping2, Date2
FROM Table1
UNION ALL
SELECT name, Email, Address, Order3, Shipping3, Date3
FROM Table1
ORDER BY Name, Date;
SqlFiddle here
(The column names are set by the first select in the UNION, and the ORDER is applied to the final UNIONed data)

Join two tables with different field value

Would it be possible to join two tables with different field values? I am using MS SQL Server 2008.
Table A (original image, thanks to #EdwardRusu for translating images to text):
+ ----- + --------- + -------- + ----------- + ------------------ + ---------------- + ----------- +
| RecID | Member ID | LoanType | LoanSubType | Application Number | Application Date | Loan Amount |
+ ----- + --------- + -------- + ----------- + ------------------ + ---------------- + ----------- +
| 3 | 00005 | Regular | | 201604002 | 2016-02-28 | 39864.00 |
| 185 | 00005 | Special | Special ... | 201604183 | 2016-10-31 | 10000.00 |
| 318 | 00005 | Regular | | 201605063 | 2016-05-18 | 39864.00 |
| 427 | 00005 | Regular | | 201608021 | 2016-08-18 | 39872.00 |
| 486 | 00005 | Special | Special ... | 201609044 | 2016-09-07 | 10000.00 |
| 589 | 00005 | Regular | | 201611008 | 2016-11-04 | 39872.00 |
| 689 | 00005 | Regular | | 201702004 | 2017-02-02 | 39872.00 |
+ ----- + --------- + -------- + ----------- + ------------------ + ---------------- + ----------- +
Table B (original image):
+ --------------- + --------- + ------ + ----- + ---------- + -------- + -------- + -------- +
| ProjectAcctCode | Member ID | TMonth | TYear | TLastDate | TDebit | TCredit | TBalance |
+ --------------- + --------- + ------ + ----- + ---------- + -------- + -------- + -------- +
| 105350500 | 00005 | 1 | 2017 | 2017-01-31 | 0.00 | 2952.00 | -2952.00 |
| 105350500 | 00005 | 5 | 2016 | 2016-05-31 | 73084.00 | 33220.00 | 39864.00 |
| 105350500 | 00005 | 6 | 2016 | 2016-06-30 | 0.00 | 2951.42 | -2952.42 |
| 105350500 | 00005 | 7 | 2016 | 2016-07-31 | 0.00 | 3014.14 | -3014.14 |
| 105350500 | 00005 | 8 | 2016 | 2016-08-31 | 39872.00 | 33905.26 | 5973.55 |
| 105350500 | 00005 | 9 | 2016 | 2016-09-30 | 0.00 | 2952.00 | -2952.00 |
| 105350500 | 00005 | 10 | 2016 | 2016-10-31 | 0.00 | 3014.73 | -3014.73 |
| 105350500 | 00005 | 11 | 2016 | 2016-11-30 | 39872.00 | 33905.26 | 5966.74 |
| 105351000 | 00005 | 1 | 2017 | 2017-01-31 | 0.00 | 975.03 | -975.03 |
| 105351000 | 00005 | 5 | 2016 | 2016-05-31 | 5000.00 | 1000.00 | 4000.00 |
| 105351000 | 00005 | 6 | 2016 | 2016-06-30 | 0.00 | 1000.00 | -1000.00 |
| 105351000 | 00005 | 7 | 2016 | 2016-07-31 | 0.00 | 1000.00 | -1000.00 |
| 105351000 | 00005 | 8 | 2016 | 2016-08-31 | 0.00 | 1000.00 | -1000.00 |
| 105351000 | 00005 | 9 | 2016 | 2016-09-30 | 10000.00 | 1000.00 | 9000.00 |
| 105351000 | 00005 | 10 | 2016 | 2016-10-31 | 0.00 | 955.82 | -955.82 |
| 105351000 | 00005 | 11 | 2016 | 2016-11-30 | 0.00 | 965.38 | -965.38 |
+ --------------- + --------- + ------ + ----- + ---------- + -------- + -------- + -------- +
I want to get the total TBalance from TableB grouped by MemberID, LoanType, ApplicationNo, ApplicationDate. These two tables should be joined based on LoanType and ProjAcctCode AND ApplicationDate and TLastDate. LoanType and ProjAcctCode have different values. But, "REGULAR" Loantype is equal to "105350500" ProjAcctCode and "SPECIAL LoanType" is equivalent to "105351000" ProjAcctCode.
ApplicationDate should be less than or equal to TLastDate.
So if I will generate records for "REGULAR" loan types , I should have something like this (original image):
+ -------- + -------- + ------------- + --------------- + ---------- + ------------ + --------- + --------- +
| MemberID | LoanType | ApplicationNO | ApplicationDate | LoanAmount | ProjAcctCode | TLastDate | Balance |
+ -------- + -------- + ------------- + --------------- + ---------- + ------------ + --------- + --------- +
| 000005 | Regular | 201608021 | 8/18/2016 | 39,872.00 | 105350500 | 8/31/2016 | 39,871.44 |
+ -------- + -------- + ------------- + --------------- + ---------- + ------------ + --------- + --------- +
But with my query,
SELECT a.MemberID,
(SELECT TOP (1) ApplicationNo
FROM TABLE A
WHERE (MemberID = a.MemberID) AND (ApplicationDate <= b.TLastDate)
ORDER BY ApplicationNo DESC) AS ApplicationNo,
(SELECT TOP (1) LoanAmount
FROM TABLE A AS SAL_APPLICATION_HEADER_1
WHERE (MemberID = a.MemberID) AND (ApplicationDate <= b.TLastDate)
ORDER BY ApplicationNo DESC) AS LoanAmount,
(SELECT TOP (1) ApplicationDate
FROM TABLE A AS SAL_APPLICATION_HEADER_2
WHERE (MemberID = a.MemberID)
AND (ApplicationDate <= b.TLastDate)
ORDER BY ApplicationNo DESC) AS ApplicationDate,
vwSAL_Balance_SL_1.ProjAcctCode,
b.TDebit,
b.TCredit,
b.TBalance AS Balance,
b.TLastDate
FROM TABLE A AS a
INNER JOIN TABLE B AS b ON a.MemberID = b.SLCode
GROUP BY a.MemberID,
b.TDebit,
b.TCredit,
b.TBalance,
b.ProjAcctCode,
b.TLastDate
HAVING (a.MemberID = N'00005') AND (b.TLastDate = '8/31/2016')
I got this result (original image):
+ -------- + ------------- + ---------- + --------------- + ------------ + -------- + -------- + -------- + ---------- +
| MemberID | ApplicationNo | LoanAmount | ApplicationDate | ProjAcctCode | TDebit | TCredit | Balance | TLastDate |
+ -------- + ------------- + ---------- + --------------- + ------------ + -------- + -------- + -------- + ---------- +
| 00005 | 201608021 | 39872.00 | 2016-08-18 | 105351000 | 0.00 | 1000.00 | -1000.00 | 2016-08-31 |
| 00005 | 201608021 | 39872.00 | 2016-08-18 | 105350500 | 39872.00 | 33898.45 | 5973.55 | 2016-08-31 |
+ -------- + ------------- + ---------- + --------------- + ------------ + -------- + -------- + -------- + ---------- +
This might be too long but please help. Thank you.
tl;dr Yes, it is possible. The query block at the end will give you what you want.
Yes, it is possible to join two tables with different field values as long as you know some sort of correlation between the two. I will walk you through the construction of the join statement that gives you what you want. You need three things:
1) Match MemberID and SLCode
2) Match LoanType and ProjAcctCode
3) Match the dates
MemberID and SLCode
Based on your comment above, I'm going to assume that SLCode is the same thing as MemberID in B.
select *
from A
inner join B
on B.MemberID = A.MemberID -- or B.SLCode = A.MemberID
LoanType and ProjAcctCode
In this example, you want to use a case statement in the join, something like
inner join B.ProjAcctCode = case A.LoanType when 'Regular' then 105350500 else 105351000 end
This says that if the LoanType is Regular, then only join records that have ProjAcctCode = 105350500; otherwise join records that have ProjAcctCode 105351000. (Here, LoanType only has two states, so using the else clause to capture Special loans is perfectly fine. If there are more than two states, then you must use additional conditions).
select *
from A
inner join B
on B.MemberID = A.MemberID
and B.ProjAcctCode = case A.LoanType when 'Regular' then 105350500 else 105351000 end
Dates
Getting the date filter right is immediate.
select *
from A
inner join B
on B.MemberID = A.MemberID
and B.ProjAcctCode = case A.LoanType when 'Regular' then 105350500 else 105351000 end
and A.ApplicationDate <= B.TLastDate
Group and Aggregate
Now that you have the tables joined appropriately, you just need to group and aggregate. You can group on anything from A since those fields don't change for the aggregates you want, and you just have to be a little clever in how you select things that came from B. In your question, it looks like you want ProjAcctCode (this doesn't change, so we can group on this too), TLastDate (this does change, so we need to aggregate on some criteria), and TBalance (from which we want the sum). I'm going to assume that you want the latest TLastDate, so your query will be something like
select A.MemberID,
A.LoanType,
A.ApplicationNumber,
A.ApplicationDate,
[anything else you want from A],
B.ProjAcctCode -- aggregate not needed because this doesn't change
max(B.TLastDate) as TLastDate,
sum(B.TBalance) as TBalance
from A
inner join B
on B.MemberID = A.MemberID
and B.ProjAcctCode = case A.LoanType when 'Regular' then 105350500 else 105351000 end
and A.ApplicationDate <= B.TLastDate
group by A.MemberID,
A.LoanType,
A.ApplicationNumber,
A.ApplicationDate,
[anything else you selected from A],
B.ProjAcctCode
This produces the following table
+ -------- + -------- + ----------------- + --------------- + ------------ + ---------- + -------- +
| MemberID | LoanType | ApplicationNumber | ApplicationDate | ProjAcctCode | TLastDate | TBalance |
+ -------- + -------- + ----------------- + --------------- + ------------ + ---------- + -------- +
| 00005 | Regular | 201604002 | 2016-02-08 | 105350500 | 2017-01-31 | 36913.19 |
| 00005 | Special | 201604183 | 2016-10-31 | 105351000 | 2017-01-31 | -2896.23 |
| 00005 | Regular | 201605063 | 2016-05-18 | 105350500 | 2017-01-31 | 36913.19 |
| 00005 | Regular | 201608021 | 2016-08-18 | 105350500 | 2017-01-31 | 3014.75 |
| 00005 | Special | 201609044 | 2016-09-07 | 105351000 | 2017-01-31 | 6103.77 |
| 00005 | Regular | 201611008 | 2016-11-04 | 105350500 | 2017-01-31 | 3014.74 |
+ -------- + -------- + ----------------- + --------------- + ------------ + ---------- + -------- +
Note: The loan with ApplicationNumber 201702004 doesn't appear in the final result because it gets filtered out by date (i.e. its application date is greater than all TLastDate in B).
I just use UNION (per LoanType) in my query to get the desire result.

Resources