Access 2019 Query through 2 tables - sql

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

Related

What is the most appropriate logic to add rows in table

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

Row number in query result

I have query to get firms by theirs sales last year.
select
Name,
Sale
from Sales
order by
Sale DESC
and I get
Firm 2 | 200 000
Firm 1 | 190 000
Firm 3 | 100 000
And I would like to get index of row in result. For Firm 2 I would like to get 0 (or 1), for Firm 3 1 (or 2) and etc. Is this possible? Or at least create some sort of autoincrement column. I can use even stored procedure if it is needed.
Firebird 3.0 supports row_number() which is the better way to do this.
However for Firebird 2.5, you can get what you want with a correlated subquery:
select s.Name, s.Sale,
(select count(*) from Sales s2 where s2.sale >= s.sale) as seqnum
from Sales s
order by s.Sale DESC;

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

SQL: Select all from column A and add a value from column B if present

I'm having quite an easy problem with SQL, I just can't word it properly (therefore I didn't find anything in google and my title probably is misleading)
The problem is: I have a big table containing transaction informations in the form (ID, EmployeeID, Date, Value) (and some more, but only those matter currently) and a list of all EmployeeIDs. What I want is a result table showing all employee IDs with their aggregated value of transactions in a given timespan.
The problem is: How do I get those employees into the result table that don't have an entry for the given time period?
e.g.
ID EMPLID DATE VALUE
1 1 2013-01-01 1000
2 2 2013-02-02 2000
3 1 2013-01-03 3000
4 2 2013-04-01 2000
5 2 2013-03-01 2000
6 1 2013-02-01 4000
EMPLID NAME
1 bob
2 alice
And now I want the aggregated value of all transactions after 2013-03-01 like this
EMPLID VALUE
1 0 <- how to get this based on the employee table?
2 4000
The SQL Server in use is Firebird and I connect to it through JDBC (if that matters)
SELECT a.EmpID, a.Name,
COALESCE(SUM(b.Value), 0) TotalValue
FROM Employee a
LEFT JOIN Transactions b
ON a.EmpID = b.EmpID AND
b.Date >= '2013-03-01'
GROUP BY a.EmpID, a.Name
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins

oracle sql query to get data from two tables of similar type

I have two tables ACTUAL AND ESTIMATE having unique column(sal_id, gal_id, amount, tax).
In ACTUAL table I have
actual_id, sal_id, gal_id, process_flag, amount, tax
1 111 222 N 100 1
2 110 223 N 200 2
In ESTIMATE table I have
estimate_id, sal_id, gal_id, process_flag, amount, tax
3 111 222 N 50 1
4 123 250 N 150 2
5 212 312 Y 10 1
Now I want a final table, which should have record from ACTUAL table and if no record exist for sal_id+gal_id mapping in ACTUAL but exist in ESTIMATE, then populate estimate record (along with addition of amount and tax).
In FINAL table
id sal_id, gal_id, actual_id, estimate_id, total
1 111 222 1 null 101 (since record exist in actual table for 111 222)
2 110 223 2 null 202 (since record exist in actual table for 110 223)
3 123 250 null 4 51 (since record not exist in actual table but estimate exist for 123 250)
(for 212 312 combination in estimate, since record already processed, no need to process again).
I am using Oracle 11g. Please help me on writing a logic in a single sql query?
Thanks.
There are several ways to write this query. One way is to use join and coalesce:
select coalesce(a.sal_id, e.sal_id) as sal_id,
coalesce(a.gal_id, e.gal_id) as gal_id,
coalesce(a.actual_value, e.estimate_value) as actual_value
from actual a full outer join
estimate e
on a.sal_id = e.sal_id and
a.gal_id = e.gal_id
This assumes that sal_id/gal_id provides a unique match between the tables.
Since you are using Oracle, here is perhaps a clearer way of doing it:
select sal_id, gal_id, actual_value
from (select *,
max(isactual) over (partition by sal_id, gal_id) as hasactual
from ((select 1 as isactual, *
from actual
) union all
(select 0 as isactual, *
from estimate
)
) t
) t
where isactual = 1 or hasactual = 0
This query uses a window function to determine whether there is an actual record with the matching sal_id/gal_id. The logic is to take all actuals and then all records that have no match in the actuals.