Updating a field based on multiple criteria - sql

For reference, this isn't a homework assignment, but something I am doing at work. Unfortunately, my SQL skills are not very good, so I'm not sure how to go about doing this. I know there are some great SQL guys here, so I was hoping you could help me out!
At the very least, any guidance on the general structure of the query would be awesome! The primary issue I have is that the heart of this query will have to be run multiple times (ie. A loan has multiple rows that have Payoff = 1)
Thanks!
Suppose you have the following tables:
Payoffs:
P_ID | DebtID (FK) | LoanID | Payoff | PayoffAmount
=====|=============|========|========|=============
1 | 1 | 10 | 1 | 0.00
2 | 2 | 10 | 1 | 0.00
3 | 3 | 27 | 0 | 0.00
4 | 4 | 14 | 1 | 0.00
5 | 5 | 10 | 0 | 0.00
Debts:
DebtID | CurrAccountBal
=======|===============
1 | 2375.00
2 | 1000.00
3 | 2300.00
4 | 2400.00
5 | 500.00
Given a LoanID, if Payoffs.Payoff = "1", then take the amount in Debts.CurrAccountBalance and insert it into Payoffs.PayoffAmount.

This should work in most (if not all) database engines:
UPDATE Payoffs
SET PayoffAmount =
(SELECT CurrAccountBal
FROM Debts
WHERE Payoffs.DebtID = Debts.DebtID
)
WHERE Payoff = 1
AND LoanID = [insert desired LoanID here];

Related

Summing all values with same ID in a column give me duplicated values in SQL?

I am trying to sum all the columns that have the same ID number in a specified date range, but it always gives me duplicated values
select pr.product_sku,
pr.product_name,
pr.brand,
pr.category_name,
pr.subcategory_name,
a.stock_on_hand,
sum(pr.pageviews) as page_views,
sum(acquired_subscriptions) as acquired_subs,
sum(acquired_subscription_value) as asv_value
from dwh.product_reporting pr
join dm_product.product_data_livefeed a
on pr.product_sku = a.product_sku
where pr.fact_day between '2022-05-01' and '2022-05-30' and pr.pageviews > '0' and pr.acquired_subscription_value > '0' and store_id = 1
group by pr.product_sku,
pr.product_name,
pr.brand,
pr.category_name,
pr.subcategory_name,
a.stock_on_hand;
This supposes to give me:
Sum of all KPI values for a distinct product SKU
Example table:
| Date | product_sku |page_views|number_of_subs
|------------|-------------|----------|--------------|
| 2022-01-01 | 1 | 110 | 50 |
| 2022-01-25 | 2 | 1000 | 40 |
| 2022-01-20 | 3 | 2000 | 10 |
| 2022-01-01 | 1 | 110 | 50 |
| 2022-01-25 | 2 | 1000 | 40 |
| 2022-01-20 | 3 | 2000 | 10 |
Expected Output:
| product_sku |page_views|number_of_subs
|-------------|----------|--------------|
| 1 | 220 | 100 |
| 2 | 2000 | 80 |
| 3 | 4000 | 20 |
Sorry I had to edit to add the table examples
Since you're not listing the dupes (assuming they are truly appearing as duplicate rows, and not just multiple rows with different values), I'll offer that there may be something else that's at play here - I would suggest for every string value in your result set that's part of the GROUP BY clause to apply a TRIM(UPPER()) as you might be dealing with either a case insensitivity or trailing blanks that are treated as unique values in the query.
Assuming all the columns are character based:
select trim(upper(pr.product_sku)),
trim(upper(pr.product_name)),
trim(upper(pr.brand)),
trim(upper(pr.category_name)),
trim(upper(pr.subcategory_name)),
sum(pr.pageviews) as page_views,
sum(acquired_subscriptions) as acquired_subs,
sum(acquired_subscription_value) as asv_value
from dwh.product_reporting pr
where pr.fact_day between '2022-05-01' and '2022-05-30' and pr.pageviews > '0' and pr.acquired_subscription_value > '0' and store_id = 1
group by trim(upper(pr.product_sku)),
trim(upper(pr.product_name)),
trim(upper(pr.brand)),
trim(upper(pr.category_name)),
trim(upper(pr.subcategory_name));
Thank you guys for all your help, I found out where the problem was. It was mainly in the group by when I removed all the other column names and left only the product_sku column, it worked as required

Join logic between tables without an obvious join condition

I've got 2 tables, one with an area, actions and quantities, and the other with prices and the goal is to combine the two in a view
table1
areaid integer
bananaunits integer
kilometers_ran integer
dogecoins integer
areaid | bananaunits | kilometers_ran | dogecoin
1 | 0 | 1 | 10
2 | 4 | 2 | 100
table2
rateid integer
description text
cost_per_unit integer
rateid | description | cost_per_unit
1 | price per banana | 0.5
2 | price per kilometers run | 2
3 | price per doge | 1
The intended outcome is to have a view which has the fields as following:
areaid, rateid, description, cost_per_unit, units, combined_cost
areaid| rateid| description| cost_per_unit| units| total_cost
1 | 1 | price per banana | 0.5 | 0 | 0
1 | 2 | per kilometers run | 2 | 1 | 2
1 | 3 | price per doge | 1 | 10 | 10
2 | 1 | price per banana | 0.5 | 4 | 2
2 | 2 | per kilometers run | 2 | 2 | 4
2 | 3 | price per doge | 1 | 100 | 100
In other words, I need to present all the rates per area in individual rows. how to achieve this?
Edit: current query that doesnt work
select areaid, rateid, description, cost_per_unit, units, combined_cost from table1,table2
Since you don't have a joining key and you want a row for each of combination of the area and rates, you're basically looking for a CROSS JOIN also called cartesian product

How can I SELECT MAX(VALUE) from duplicate values which occur multiple time within each month?

I have records for each user which occur multiple times each month. I wish to select just the highest value from the repeated values for each month for each user.
Table schema
custacc
ID | ac_no | DODSTART | od_limit
---+--------+------------+----------
1 | 110011 | 2019-02-10 | 200,000
2 | 110011 | 2019-02-12 | 120,000
3 | 110014 | 2019-02-10 | 70,000
4 | 110014 | 2019-02-12 | 10,000
5 | 110009 | 2019-02-10 | 30,000
customer
ID | cust_no | name | cust_type
---+---------+-------+----------
1 | 110011 | Jame | M
2 | 110014 | Fred | N
3 | 110009 | Ahmed | M
How can I achieve this>
What I tried so far:
SELECT
custacc.ac_no,
custacc.od_limit,
custacc.DODSTART,
customer.name,
custacc.gl_no,
custacc.USERNAME,
customer.cust_type
FROM
custacc
LEFT JOIN
customer ON custacc.ac_no = customer.cust_no
INNER JOIN
(SELECT
MAX(DODSTART) LAST_UPDATE_DATE_TIME,
ac_no
FROM
custacc
GROUP BY
ac_no) s2 ON custacc.ac_no = s2.ac_no
AND custacc.DODSTART = s2.LAST_UPDATE_DATE_TIME
WHERE
custacc.od_limit != 0.00
The query doesn't return the expected result.
Try this(add columns that you need):
This is Oracle solution since you didn't mention it in your question:
SELECT ID,MAX(OD_LIMIT) OVER(PARTITION BY ID,EXTRACT(MONTH FROM DODSTART)) FROM CUSTACC;

Nested Criteria/Filters in MS Access Query

Could anyone give me some idea on how I can select/update records in Access based on the data and criteria below?
Background: Headcount=1 should be set for all records except to those with duplicate records/roles (by ApptID). For those count(Headcount)>1, I have to set Headcount=0 for the record with:
Right(Empcode,5)<>Right(ApptID,5) and Fixed i.e. 100005-300678
If both Cont, just the Right(Empcode,5)<>Right(ApptID,5) record i.e. 100006-300583
If 2 similar APPTID records does not contain an empcode that has 5 digits similar with ApptID (i.e. 100007), and both are fixed or cont, whichever has the lowest FTE per will have Headcount=0 i.e. 100007-300295 / 100008-300419
APPTID | EmpCode | FTE | Status | HEADCOUNT
100001 | 300001 | 1.0 | Cont | 1
100002 | 300002 | 0.9 | Cont | 1
100003 | 300003 | 0.8 | Fixed | 1
100004 | 300004 | 1.0 | Cont | 1
100005 | 300005 | 0.5 | Cont | 1
100005 | 300678 | 0.5 | Fixed | 1
100006 | 300006 | 0.4 | Cont | 1
100006 | 300583 | 0.4 | Cont | 1
100007 | 300295 | 0.4 | Fixed | 1
100007 | 300385 | 0.6 | Fixed | 1
100008 | 300419 | 0.4 | Cont | 1
100008 | 300902 | 0.6 | Cont | 1
Currently creating a select query first before the update query. I have managed to do the first criteria with this:
SELECT ApptID, EmpCode, FTE, Status, Headcount
FROM Staff S
WHERE S.ApptID in (
Select Tmp.ApptID FROM Staff as Tmp
Group by Tmp.ApptID
Having Sum(Tmp.Headcount)>1)
AND RIGHT(S.ApptID,5)<>RIGHT(S.EmpCode,5)
AND S.Status="Fixed";
From here, I don't know how to proceed with the 2nd and 3rd as all of my attempts results to the inclusion of other records.

SQL: Transfer from column to row, size systems, fashion

I'm struggling, hope you can help me out! The application is an ERP system in MS ACCESS for fashion retailing.
The question: How can I add a row in Table3 with the article's corresponding SizeID1, SizeID2 etc filled according to it's size system of Table2?
Table1: Article details containing size system
ArticleID | SizeType
--------------------
1 | US
2 | EU
Table2: Different size systems for different regions
SizeID | Size | SizeType
------------------------
1 | S | US
2 | M | US
3 | L | US
4 | XL | US
5 | 36 | EU
6 | 38 | EU
7 | 40 | EU
Table3: Order details
OrderID | ArticleID | Size1 | Amount1 | Size2 | Amount2 | Size3 | Amount3
-------------------------------------------------------------------------
1 | 1 | S | 1 | M | 3 | L | 1
2 | 2 | 36 | 2 | 38 | 1 | 40 | 3
3 | 2 | 36 | | 38 | | 40 |
The row with OrderID = 3 is the goal of the insery query for ArticleID 2. I can then enter the amount to the corresponding size. Thanks for your help!!
It's not entirely clear what you're trying to achieve here, but I think that might be because your database design is a bit broken.
You're probably used to working with spreadsheets, becase you seem to have designed your Table3 as if it were a spreadsheet. Any time you end up with repeating fields in a database table (eg. Size1, Size2, Size3....) then it's a sign that you need to normalise more.
Please read up on database normalisation: http://www.studytonight.com/dbms/database-normalization.php (and also google generally for database normalisation for more info).
I suspect you'll need something more like this:
Article table:
ArticleID | ArticleName | SizeType(FK to SizeType table)
1 | Blue T-shirt | 1
2 | Red T-shirt | 2
SizeType table:
SizeTypeID | SizeTypeDescription
1 | US
2 | EU
Sizes table:
SizeID | SizeType(FK) | SizeDescription
1 | 1 | 38
2 | 1 | 40
3 | 2 | M
4 | 2 | L
Items table:
ItemID | ArticleID(FK) | SizeID(FK)
1 | 1 | 1 'Blue T-shirt size 38
2 | 1 | 2 'Blue T-shirt size 40
3 | 2 | 3 'Red T-shirt size M
4 | 2 | 4 'Red T-shirt size L
Orders table:
OrderID | CustomerID (FK) | OrderDate | etc. (other info you need to store about an order)
1 | 2458 | 01/01/2001|
2 | 3452 | 02/02/2002|
Order Details table:
OrderDetailsID | OrderID(FK) | ItemID (FK) | Quantity
1 | 1 | 3 | 6
2 | 1 | 4 | 3
3 | 2 | 1 | 1
So here linking everything back, Customer with ID 2458 has ordered 6x Size M Red T-shirts and 3x Size L Red T-shirts, and Customer with ID 3452 has ordered 1x size 38 Blue T-shirt.
Note You'd also realistically have a PRICE field in either the Items table (if the price varies with the size of an item) or in the Article table (if the price is the same for every size). CustomerID would also link back to a table containing a customer's details (Name, address, username/password etc).
You might also have other things that I've not shown here, for example in either your Articles table or your Items table you'll probably have a supplierID which tells you who you buy that item from, as well as a supplierItemNo which would be a unique code (barcode?) which you use to order that item.
Once your database is structured properly it will be much easier to write queries to insert records etc.