SAP infoset table connection - abap

I'm new in SAP and I have a question. I have an infoset that has 3 tables that contain customer information and shopping made.
Currently I get a report that contains the details about the customer and there is a column that indicates whether the customer bought during a certain sale . I get an offer date and check the table (not linked to the 3 tables) if that customer made a purchase on the date.
Now I have to do something more complicated. I have a date and time of sale, and I have to return a report that contains the names of all the customers, for customers who did buy during the sale, to register all the amounts they bought ( the sale is one hour in day for week)
That's what I get until now:
Customer 1 , id1 , x
Customer 2 , id2 , V
Customer 3 , id3 , x
This means that customer A actually bought in the sale. And now I have to get:
Customer 1 , id1 , x
Customer 2 , id2 , 30$, DateTime1
Customer 2 , id2 , 10$, DateTime2
Customer 2 , id2 , 15$, DateTime3
Customer 3 , id3 , x
My problem is that when I connect the table with all the customers' shopping, I get every customer he has ever made. And if I do CHECK for the date and time condition all customers who have not bought the offer are deleted. I mean I only get the Customer 2.
I add the table as "left outer". What should I do ?

Related

Getting price out of specific column based on criteria from a different table

I have three tables linked. One table has a column for part numbers and then 4 different columns for price based on what contract a customer is on. Another table has the customer ID and the contract they belong to and the third table has the sales data by customer and part number ordered.
I have the sales table and the customer table joined by customer ID and the contract table joined to the sales table by part number. Is it possible to write a query that would show the customer ID, the part number ordered, the contract they belong to, and then the price for that part number coming from the column for the specified contract. The contract numbers are the column headers in that table. The code I have so far is below, just need to add price in the SELECT clause but don't know how to only select from a specific column based on criteria from another table.
SELECT [Sales].[Customer ID], [Sales].[Item ID], [Customers].[Contract Number],
FROM ([Sales] INNER JOIN [Customers] ON [Sales].[Customer ID] = [Customers].[Customer ID])
INNER JOIN [Contracts] ON [Sales].[Item ID] = [Contracts].[Item ID];
Sales Table
Customer ID
Item ID
Customer 1
Item 1
Customer 2
Item 2
Customer 3
Item 1
Customer 2
Item 3
Customer Table
Customer ID
Contract
Customer 1
Contract 1
Customer 2
Contract 3
Customer 3
Contract 4
Customer 4
Contract 2
Contract Table
Item ID
Contract 1
Contract 2
Contract 3
Contract 4
Item 1
$20.00
$22.00
$24.00
$26.00
Item 2
$3.00
$4.50
$5.00
$6.00
Item 3
$45.00
$48.00
$50.50
$52.00
Hoping to get an output like:
Customer ID
Item ID
Contract
Price
Customer 1
Item 1
Contract 1
$20.00
Customer 2
Item 2
Contract 3
$5.00
Customer 3
Item 1
Contract 4
$26.00
Customer 2
Item 3
Contract 3
$50.50
Options - examples use fields without spaces in naming:
DLookup domain aggregate function
SELECT Customer.CustomerID, Sales.ItemID, Customer.Contract,
DLookUp("[" & Replace([Contract], " ", "") & "]","Contract","ItemID='" & [ItemID] & "'") AS Amt
FROM Customer INNER JOIN Sales ON Customer.CustomerID = Sales.CustomerID;
UNION query to rearrange the Contract fields to normalized structure and then 2 more queries
SELECT ItemID, Contract1 AS Amt, "Contract 1" AS Contract FROM Contract
UNION SELECT ItemID, Contract2, "Contract 2" FROM Contract
UNION SELECT ItemID, Contract3, "Contract 3" FROM Contract
UNION SELECT ItemID, Contract4, "Contract 4" FROM Contract;
SELECT Customer.CustomerID, Sales.ItemID, Customer.Contract
FROM Customer INNER JOIN Sales ON Customer.CustomerID = Sales.CustomerID;
SELECT Query2.CustomerID, Query1.ItemID, Query2.Contract, Query1.Amt
FROM Query2 INNER JOIN Query1
ON (Query2.Contract = Query1.Contract) AND (Query2.ItemID = Query1.ItemID);
avoid the DLookup and UNION by normalizing data structure

How can I find records that are out of order with respect to its previous record and a column?

I have a table of payment records for contracts. Each contract is paid by monthly payments.
The table has following fields:
ID (automatically assigned when a payment record is created)
payment_number (character array of digits, incremented over months, e.g. "1", "2", "3")
payment_status ("Received", "Rejected", "Approved", "Processed")
contract_ID (character array of letters and digits)
I suspected that the status of a payment can't be more advanced than the status of its previous payment. For example, if the previous payment has status "Received", then the status of the payment can only be "Received".
I was wondering how to find all the counter examples in the table?
(Maybe also the contract group of payments containing counter examples, so that I can see the statuses of counter example payments and of their previous payments)
ID contract_ID payment_number payment_status
1 contract1 1 Processed
2 contract1 2 Received
3 contract2 1 Processed
4 contract2 2 Approved
5 contract1 3 Approved
6 contract2 3 Processed
I expect it outputs something like:
ID contract_ID payment_number payment_status
2 contract1 2 Received
5 contract1 3 Approved
and
ID contract_ID payment_number payment_status
4 contract2 2 Approved
6 contract2 3 Processed
Thanks.
Taking this question on its individual merit and allowing for certain misgivings and ambiguities as mentioned in the comments, I think this is an easily comprehended solution:
create table #payments
(
id int,
contract_ID varchar(20),
payment_number int,
payment_status varchar(20)
);
insert #payments(id, contract_id, payment_number, payment_status)
values (1, 'contract1', 1, 'Processed'),
(2, 'contract1', 2, 'Received'),
(3, 'contract2', 1, 'Processed'),
(4, 'contract2', 2, 'Approved'),
(5, 'contract1', 3, 'Approved'),
(6, 'contract2', 3, 'Processed');
-- provide an ordering to the statuses according to the question text.
-- assumption: rejected/approved sit in the same lifecycle position and are mutually exclusive
with payments as
(
select p.*, t.statusIndex
from #payments p
join (
values ('Received', 0),
('Rejected', 1),
('Approved', 1),
('Processed', 2)
) t (payment_status, statusIndex) on t.payment_status = p.payment_status
)
select p.id,
p.contract_ID,
invalid_payment_number = p.payment_number,
invalid_payment_status = p.payment_status,
prior_payment_number = pp.payment_number,
prior_payment_status = pp.payment_status
from payments p
cross apply (
select pp.payment_number, pp.payment_status
from payments pp
where pp.contract_id = p.contract_id
and pp.payment_number < p.payment_number
and pp.statusIndex >= p.statusIndex
) pp
order by p.contract_id,
p.payment_number;
The logic of this query, in "plain English", is:
For all payments:
find any "prior" payment rows (rows which have the same contractId,
and which have a lower payment_number),
and where the prior payment row has a status which is logically later or equal to the status of this payment, given the possible lifecycle of the payment.
If any such rows are found, return the original row along with the prior payment row or rows, since these represent "invalid" logical progressions.

SQL Group by prevents summing across multiple records

I am trying to sum the amount paid across multiple entries in the Payment table and show who the buyers were for that Order
so if two people made payments on one order it would show their combined payments and show who the people who made the payment were. So if Bob and Sue made 10 dollar payments on a 30 dollar bill it would show
Order Buyer Paid Owes
1 Bob 20 10
1 Sue 20 10
but i'm currently at
Order Paid Owes
1 20 10
How do I add in the buyers? possibly with a join?
Currently I have.
Select Order.Orderid, sum(Payment.amount) as "Paid", Order.Price-sum(Payment.amount) as "Owes"
from order, payment
where payment.orderId = order.orderid
group by (order.orderid, order.price)
payment has a buyerId and orderid as foreign keys since it is an m to n relation.
As you mention in your comment when you join the buyer it does not give you the desired output which is the sum of all payments. To get the buyers and the sum of all payments joining another instance of the payments table and using that to calculate the sum will do the trick.
SELECT
Order.Orderid,
Buyer.Name,
SUM(PaymentSum.amount) AS 'Paid',
Order.Price-SUM(PaymentSum.amount) AS 'Owes',
FROM
Order
JOIN Payment
ON Order.Orderid = Payment.Orderid
JOIN Buyer
ON Payment.BuyerId Buyer.BuyerId
JOIN Payment AS PaymentSum
ON Order.Orderid = PaymentSum.Orderid
GROUP BY
Order.Orderid,
Order.Price,
Buyer.Name

How to delimit a population based on the dates that accounts were opened on in teradata?

CUST_ID ACCT_ID FICO_SCORE DATE_APPLICATION_RECEIVED
1 48378281 2,200,263,271 577 5/3/2001
2 48378281 2,346,832,797 611 5/14/2003
3 48378281 2,210,263,271 560 5/2/2002
4 48378281 2,416,532,797 575 5/14/2005
Say that I have a list of customers with multiple accounts with my company in teradata, and I have their fico scores, and the date that their application for a new account with us are opened. A customer must have more than 2 accounts and may have up to 5 accounts. Above is how that table would look like for just one customer. How do I now delimit this population to just those customers that have accounts where their opening date was at least 6 months apart from each other for between their first opened account and second opened account? I just need count(unique(cust_id)) at the end.
If i understand you correctly you only care for the first two accounts being at least 6 months apart?
SELECT COUNT(*)
FROM
(
SELECT CUST_ID
FROM tab
QUALIFY -- only the first account of a customer
ROW_NUMBER()
OVER (PARTITION BY CUST_ID
ORDER BY DATE_APPLICATION_RECEIVED) = 1
AND -- at least six months between this and the next row
ADD_MONTHS(DATE_APPLICATION_RECEIVED, 6)
< MIN(DATE_APPLICATION_RECEIVED)
OVER (PARTITION BY CUST_ID
ORDER BY DATE_APPLICATION_RECEIVED
ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING)
) AS dt

Trying to count # distinct values of a field based on value of a different field

Looking for some help with my SQL query. I am trying to find a way to specify cases in which a customer purchases or sells at two different stores, but if they purchase at one store and sell at another, I don't care or want that to count.
I have tried this -
Select count(distinct store) OVER(Partition BY Customer)
but it doesn't like the distinct and causes an error. When I dont specify distinct, it will give me the count of all observations of that customer, instead of just the count of # of stores that they purchased from, or sold to.
Based on the data below, customer D is the type im looking to filter for.
My Raw Data:
Customer Type Qty Store
A Purchase 1 2
A Purchase 2 2
A Sale 3 1
B Sale 24 1
B Sale 12 1
C Purchase 4 2
D Sale 12 2
D Purchase 4 2
D Purchase 2 1
D Purchase 2 1
Any ideas?
select customer
from your_table
group by customer, type
having count(distinct store) > 1
Don't you just want to GROUP?
Select Count(store) FROM Blah GROUP BY Customer, Store
Edit: Ah I see what you want - you want a count of store over customer, sorry misread it!