What is the most appropriate logic to add rows in table - sql

I have following table structure (simplified to make essential things clear), which lists Top 3 bank customers in each category of loan and branch of the bank. SNO column is rank of the customer, value of which is up to 3.
Loan Category
SNO
Branch
Customer Name
Amount
Home Loan
1
abc
Piyush
10000
Home Loan
2
abc
Shyam
5000
Home Loan
3
abc
Kamal
2000
Home Loan
1
xyz
Xman
50000
Home Loan
2
xyz
Shyam
20000
Auto Loan
1
abc
Birendra
10000
Personal Loan
1
xyz
Gyan
5000
Personal Loan
2
xyz
Prakash
2000
I am trying to make another table such that, If there are less than 3 customers in each loan category and branch, Insert a dummy row for each branch and category with values of customer name and amount as NULL.
Essentially, I am trying to get following table.
Loan Category
SNO
Branch
Customer Name
Amount
Home Loan
1
abc
Piyush
10000
Home Loan
2
abc
Shyam
5000
Home Loan
3
abc
Kamal
2000
Home Loan
1
xyz
Xman
50000
Home Loan
2
xyz
Shyam
20000
Home Loan
3
xyz
added row
Auto Loan
1
abc
Birendra
10000
Auto Loan
2
abc
added row
Auto Loan
3
abc
added row
Auto Loan
1
xyz
added row
Auto Loan
2
xyz
added row
Auto Loan
3
xyz
added row
Personal Loan
1
xyz
Gyan
5000
Personal Loan
2
xyz
Prakash
2000
Personal Loan
3
xyz
added row
Personal Loan
1
abc
added row
Personal Loan
2
abc
added row
Personal Loan
3
abc
added row
I have solved this problem by using Loop iterating over all category and branch and inserting dummy row, if max(sno) < 3 for each category/branch. But, I am looking for appropriate logic without iterating over all category and branch. In my actual table, there are thousands of branch values and more than 100 categories. So, iterating over all combination of category and branch is very expensive in terms of performance.
I need to write some good logic preferably using SQL constructs only or not using any loop.

Ok. So you must have some tables where branch and category is listed in single or multiple tables. Lets take it as your branch and category tables and you must have some query which produced the result mentioned in the question. Lets call it your_query.
You need to generate 3 records per branch per category.
Select c.category as loan_category,
L.lvl as sno,
B.branch,
Q.cutomername,
Q.amount
From category c
Cross join branch b
Cross Join (select level lvl from dual connect by level <= 3) l
Left Join your_query q on q.branch = c.branch
and q.category = c.category
and l.lvl = q.sno
Ordet by c.category, B.branch, L.lvl

Related

Access 2019 Query through 2 tables

Table A
ID Name Pay Colleage
1 aaa 15,000 1
2 bbb 25,000 2
Table B : Deduction Money
ID Min Max Colleage1 Colleage2 Colleage3 Colleage4
1 10,001 20,000 1,000 2,000 3,000 4,000
2 20,001 30,000 2,000 3,000 4,000 5,000
I have to take each employee's deduction money in Table B.
Given Table B says, aaa's deduction money will be 1,000.
Because its range of pay is between 10,001~20,000
and it has 1 colleage.
So if i follow it on Table B. I can find the amount is 1,000.
As same way, bbb will be 3,000.
But I can't get the proper value.
I want query syntax to use for access 2019.
So help me pz.
You can join the tables and use CHOOSE() to select the correct deduction:
SELECT a.*, CHOOSE(a.Colleage, b.Colleage1, b.Colleage2, b.Colleage3, b.Colleage4) AS Deduction
FROM TableA AS a INNER JOIN TableB AS b
ON a.Pay >= b.Min AND a.Pay <= b.Max

How to Introduce new table

I've 3 tables Tickets, Sales, Payments. Tickets and Payments have sale_id in it as a foreign key
Ticcekt Table Data
TicketID price service sale_id
1 19 City 1
2 19 City 1
3 15 St. Kilda 2
4 36 City 3
Sale table data
SaleID sale_time
1 2017-03-01
2 2017-03-01
3 2017-03-01
Payment table data
PaymentID amount sale_id payment_type
1 36 1 cash
2 15 2 eft
3 18 3 cash
4 18 3 eft
So Tickets and Payments table may have multiple records against 1 sale. If I have to right query to see the payment amount group by Ticket_table service column and I only have inner join option and also i can't write sub queries, than how i'll introduce a new table to make this work with a simple inner join query.
Currently if i do the inner join it returns me duplicate values. I'm doing this in Sisense where my only option is to introduce new tables to fix this.
So what would be the new table which comes in between and make this 1 to 1 relation
Edit
Desired result
Service payment_amount
City 72
St.kilda 15

SQL Server query for hierarchical group wise sum for the chart of accounts

I have created a query for displaying account name and balance as follows.
Table Structure is as follows.
Level Account Balance AccountCode ParentAccountCode
1 Revenue 0 41 NULL
2 Direct Income 0 411 41
3 Sales 0 4111 411
4 Sales 0 41111 4111
5 In Store Sales 100 411111 41111
5 Online Sales 200 411112 41111
2 Indirect Income 0 412 41
3 Interest 0 4121 412
4 Bank Interest 0 41211 4121
5 Bank Interest A 400 412111 41211
5 Bank Interest B 700 412112 41211
3 Other Income 0 4122 412
4 Other Income 0 41221 4122
5 Other Income 900 412211 41221
All the above fields are from same table.
But only level 5 accounts have balance.
I want to write the sql query to show addition of accounts of child account in parent accounts hierarchically and level wise.
Expected result is as follows
Level Account Balance
1 Revenue 2300
2 Direct Income 300
3 Sales 300
4 Sales 300
5 In Store Sales 100
5 Online Sales 200
2 Indirect Income 2000
3 Interest 1100
4 Bank Interest 1100
5 Bank Interest A 400
5 Bank Interest B 700
3 Other Income 900
4 Other Income 900
5 Other Income 900
Thanks.
Edited to match your structure:
with AccountBalanceHierarchy as
(
-- root level
select AccountCode
, ParentAccountCode
, Account
, 1 as [Level]
, cast('-' + cast (AccountCode as nvarchar(10)) + '-' as nvarchar(100)) as Hierarchy -- build hierarchy in format -L0-L1-L2-...-Ln--
, Balance
from AccountBalance
where ParentAccountCode is null
union all
-- recursive join on parent, building hierarchy
select CurrentLevel.AccountCode
, CurrentLevel.ParentAccountCode
, CurrentLevel.Account
, ParentLevel.[Level]+1 as [Level]
, cast(ParentLevel.Hierarchy + cast (CurrentLevel.AccountCode as nvarchar(10))+ '-' as nvarchar(100)) as Hierarchy
, CurrentLevel.Balance
from AccountBalance CurrentLevel
join AccountBalanceHierarchy ParentLevel on CurrentLevel.ParentAccountCode = ParentLevel.AccountCode
)
select CurrentHierarchyLevel.[Level]
, replicate(' ', CurrentHierarchyLevel.[Level]) + CurrentHierarchyLevel.Account as Account
, sum(case when CurrentHierarchyLevel.Hierarchy = substring(ChildLevel.Hierarchy, 1, len(CurrentHierarchyLevel.Hierarchy)) then ChildLevel.Balance else 0 end)
from AccountBalanceHierarchy as CurrentHierarchyLevel
cross
join AccountBalanceHierarchy as ChildLevel
group by CurrentHierarchyLevel.[Level], CurrentHierarchyLevel.Account,CurrentHierarchyLevel.Hierarchy
order by CurrentHierarchyLevel.Hierarchy
Explanation:
In the hierarchy CTE, we build a hierarchy of your nodes starting with the root level (where ParentAccountCode is null) and then we join other levels through the ParentAccountCOde = AccountCode while increasing the Level.
In the CTE we also build a flat structure of your nodes, in a form of -L0-L1-...-Ln for each of the nodes. The root will have this structure as -41-, then its children with IDs 411 and 412 will have the structure -41-411- and -41-4112-, 411's child with code 4111 will be -41-411-4111-. Your AccountCodes actually make this unnecessary, because they match eachother, but I have a feeling they might not necessarily be the true IDs since you just edited your question a couple of times. The solution with building the structure like in the code makes this independed of IDs given to the accounts.
Then finally we select from the CTE and get the balance for all cross joining all the nodes and matching the generated flat structure of the children with the current structure. We know that the children of a given node will have the same beginning of the structure as the parent. Example following above: all children of root item 1 with structure -1- will have -1- at the beginning, e.g. -1-3-, -1-3-5-, -1-2-; or all children of -1-3-5- will have -1-3-5- at the beginning (e.g. -1-3-5-10). This is done in the SUM by using CASE statement - if the beginning of the structure matches (substring of the child structure is equal to the parent's structure), use the current_value for sum.
Here's the sqlfiddle with schema and query http://sqlfiddle.com/#!6/09ec8/1 and resulting data which matches your expected result:
Level Account Balance
----------- ------------------------------------------ ---------------------
1 Revenue 2300,00
2 Direct Income 300,00
3 Sales 300,00
4 Sales 300,00
5 In Store Sales 100,00
5 Online Sales 200,00
2 Indirect Income 2000,00
3 Interest 1100,00
4 Bank Interest 1100,00
5 Bank Interest A 400,00
5 Bank Interest B 700,00
3 Other Income 900,00
4 Other Income 900,00
5 Other Income 900,00

Joining to another table only on the first occurrence of a field

Note: I have tried to simplify the below to make it simpler both for me and for anyone else to understand, the tables I reference below are in fact sub-queries joining a lot of different data together from different sources)
I have a table of purchased items:
Items
ItemSaleID CustomerID ItemCode
1 100 A
2 100 B
3 100 C
4 200 A
5 200 C
I also have transaction header and detail tables coming from a till system:
TranDetail
TranDetailID TranHeaderID ItemSaleID Cost
11 51 1 $10
12 51 2 $10
13 51 3 $10
14 52 4 $20
15 52 5 $10
TranHeader
TranHeaderID CustomerID Payment Time
51 100 $100 11:00
52 200 $50 12:00
53 100 $20 13:00
I want to get to a point where I have a table like:
ItemSaleID CustomerID ItemCode Cost Payment Time
1 100 A $10 $120 11:00
2 100 B $10 11:00
3 100 C $10 11:00
4 200 D $20 $50 12:00
5 200 E $10 12:00
I have a query which produces the results but when I add in the ROW_NUMBER() case statement goes from 2 minutes to 30+ minutes.
The query is further confused because I need to supply the earliest date relating to the list of transactions and the total price paid (could be many transactions throughout the day for upgrades etc)
Query below:
SELECT ItemSaleID
, CustomerID
, ItemCode
, Cost
, CASE WHEN ROW_NUMBER() OVER (PARTITION BY TranHeaderID ORDER BY ItemSaleID) = 1
THEN TRN.Payment ELSE NULL END AS Payment
FROM Items I
OUTER APPLY (
SELECT TOP 1 SUB.Payment, Time
FROM TranHeader H
INNER JOIN TranDetail D ON H.TranHeaderID = D.TranHeaderID
OUTER APPLY (SELECT SUM(Payment) AS Payment
FROM TranHeader H2
WHERE H2.CustomerID = Items.CustomerID
) SUB
WHERE D.CustomerID = I.CustomerID
) TRN
WHERE ...
Is there a way that I can only show payments for each occurrence of the customer ID whilst maintaining performance

Show account balance from multiple tables

I am having following two table which stores information about Credit and Debit records.
voucherCr table contains
voucherType voucherPrefix voucherNo crparty cramount
SALES S 1 1 43000
SALES S 2 1 10000
voucherDr table contains
voucherType voucherPrefix voucherNo drparty dramount
SALES S 1 5 43000
SALES S 2 5 10000
Now here, in SALES voucher S/1, party 1 has been credit with 43000 amount agains party 5 of same amount. Same is with SALES voucher S/2, where party 1 has been credited with 10000 amount against party 5 of same amount.
Now I want to display results as follows If i query about party 1
PARTY CREDIT DEBIT DEBITPARTY voucherType voucherPrefix voucherNo
1 43000 5 SALES S 1
1 10000 5 SALES S 2
Please help
Try to use this query. Is it possible in your case that one dramount is divided to many rows in voucherDr? For example 43000->40000+3000
select
vc.Party,vc.CrAmount, vd.drAmount, vd.drparty,
vc.voucherType, vc.voucherPrefix, vc.voucherNo
from voucherCr vc
left join voucherDr vd on (vc.voucherType=vd.voucherType)
and (vc.voucherPrefix=vd.voucherPrefix)
and (vc.voucherNo=vd.voucherNo)
where vc.PARTY=1
If i have understood your question properly then this is what you are looking for
Select c.crParty as Party, d.dramount as credit , null as debit,
d.drParty as DEBITPARTY,c.voucherType as voucherType,
d.voucherPrefix,d.voucherNo
from VoucherCr as c inner join VoucherDr as d
on c.voucherNo=d.VoucherNo and c.voucherPrefix=d.voucherPrefix
where c.crparty=1
group by d.dramount,c.cramount,d.voucherPrefix,d.voucherNo,c.crParty,
c.voucherType,d.drParty
order by d.dramount desc
Try SQLFIDDLE