Aggregate or similar function in SQL Views - sql

There is a table CUST_ORDERS
CustID OrderID InvoiceAmt
1 1 100
1 2 60
2 3 90
3 4 10
3 5 20
I want to create a SQL VIEW for this which contains aggregate of InvoiceAmt for each Customer
CustID InvoiceAmt
1 160
2 90
3 30
As can be seen above, For CustID 1, InvoiceAmt is 100 + 60 = 160
How can this be achieved using a VIEW ?
If not, can it be achieved using triggers ?

create view
create view my_view as
select custID, sum(InvoiceAmt) sum_invoice_amt
from CUST_ORDERS
group by custID
then select from view
select * from my_view
or explicitally
select custID, sum_invoice_amt
from my_view

Related

Postgres query with limit that selects all records with similar identifier

I have a table that looks something like this:
customer_id
data
1
123
1
456
2
789
2
101
2
121
2
123
3
123
4
456
What I would like to do is perform a SELECT combined with a LIMIT X to get X number of records as well as any other records that have the same customer_id
Example query: SELECT customer_id, data FROM table ORDER BY customer_id LIMIT 3;
This query returns:
customer_id
data
1
123
1
456
2
789
I'd like a query that will look at the last customer_id value and return all remaining records that match beyond the LIMIT specified. Is it possible to do this in a single operation?
Desired output:
customer_id
data
1
123
1
456
2
789
2
101
2
121
2
123
In Postgres 13 can use with ties:
select t.*
from t
order by customer_id
fetch first 3 rows with ties;
In earlier versions you can use in:
select t.*
from t
where t.customer_id in (select t2.customer_id
from t t2
order by t2.customer_id
limit 3
);
You can use corelated subquery with count as follows:
Select t.*
From t
Where 3 >= (select count(distinct customer_id)
From t tt
where t.customer_id >= tt.customer_id)

How to pivot on 2 fields

Here is the table I have:
PeriodID RecordID Basis Amount1 Amount2
1 1 IFRS 10 100
1 2 IFRS 20 200
2 1 IFRS 15 150
2 2 IFRS 25 250
1 1 CGAAP 30 300
1 2 CGAAP 40 400
2 1 CGAAP 35 350
2 2 CGAAP 45 450
I would like to pivot on the PeriodID and Basis field so that the result would have following columns:
RecordID
Period1IFRSAmount1
Period2IFRSAmount1
PeriodID1IFRSAmount2
PeriodID2IFRSAmount2
Period1CGAAPAmount1
Period2CGAAPAmount1
PeriodID1CGAAPAmount2
PeriodID2IFRSAmount22
First of all, you need to create the ouput that you need as rows. That is why union part is really important. After you construct your data you can easily use PIVOT.
Following query written in SQL SERVER. It should be similar to other databases as well.
SELECT *
FROM
(
SELECT RecordID, 'Period' + CONVERT(VARCHAR, PeriodID) + Basis + 'Amount1' AS Basis, Amount1 AS Amount
FROM TableName
UNION ALL
SELECT RecordID, 'Period' + CONVERT(VARCHAR, PeriodID) + Basis + 'Amount2' AS Basis, Amount2 AS AMOUNT
FROM TableName
) AS Q
PIVOT (
SUM(Amount)
FOR Basis IN
(
[Period1IFRSAmount1],
[Period2IFRSAmount1],
[Period1IFRSAmount2],
[Period2IFRSAmount2],
[Period1CGAAPAmount1],
[Period2CGAAPAmount1],
[Period1CGAAPAmount2],
[Period2CGAAPAmount2]
)
) AS P

Return top 1 record based on a condition in SQL Server

I have the following table and records
How do I return all record and top 1 record where CUSTID appears more than once.
The result should like like
CUSTID ORDERID ORDERDATE ITEMPRICE
50 1 5/10/2019 10
150 2 5/10/2019 11
51 3 5/10/2019 50
Distinct CUSTID isn't working as I need to display all the columns.
Appreciate any help.
it seems you need row_number()
select a.* from
(select *,row_number()over(partition by custid order by itemprice desc)rn
from table_name
) a where a.rn=1

How do I make a query that selects where the SUM equals a fixed value

I've spent that last couple of days searching for a way to make a SQL query that searches the database and returns records where the SUM of the same ID's equal or grater then the value provided.
For this I've been using the W3schools database to test it out in the products table.
More so what I've been trying to do:
SELECT * FROM products
WHERE supplierid=? and SUM(price) > 50
in the "where supplier id" would loop through same suppliers and sum of their price higher than 50 in this case return the records.
In this case it would read supplier ID 1 then add the price of all that supplier 18+19+10=47 now 47 < 50 so it will not print those records at the end. Next supplier ID 2 22+21.35=43.35 and again would not print those records until the sum of price is higher than 50 it will print
I'm working with a DB2 database.
SAMPLE data:
ProductID ProductName SupplierID CategoryID Price
1 Chais 1 1 18
2 Chang 1 1 19
3 Aniseed 1 2 10
4 Chef Anton 2 2 22
5 Chef Anton 2 2 21.35
6 Grandma's 3 2 25
7 Uncle Bob 3 7 30
8 Northwoods 3 2 40
9 Mishi 4 6 97
10 Ikura 4 8 31
11 Queso 5 4 21
12 Queso 5 4 38
13 Konbu 6 8 6
14 Tofu 6 7 23.25
How about:
select * from products where supplierid in (
select supplierid
from products
group by supplierid
having sum(price) > 50
);
The subquery finds out all the supplierid values that match your condition. The main (external) query retrieves all rows that match the list of supplierids.
not tested, but I would expect db2 to have analytic functions and CTEs, so perhaps:
with
basedata as (
select t.*
, sum(t.price) over(partition by t.supplierid) sum_price
from products t
)
select *
from basedata
where supplierid = ?
and sum_price > 50
The analytic function aggregates the price information but does not group the resultset, so you get the rows from your initial result, but restricted to those with an aggregated price value > 50.
The difference to a solution with a subquery is, that the use of the analytic function should be more efficient since it has to read the table only once to produce the result.

complex paratition sum in postgresql

I have tables as follow:
A deliveries
delveryid clientid deliverydate
1 10 2015-01-01
2 10 2015-02-02
3 11 2015-04-08
B items in deliveris
itemid deliveryid qty status
70 1 5 1
70 1 8 2
70 2 10 1
72 1 12 1
70 3 100 1
I need to add a column to my query that gives me the qty of each part in other deliveris of the same client.
meaning that for given data of client 10 and delivery id 1 I need to show:
itemid qty status qtyOther
70 5 1 10 //itemid 70 exists in delivery 2
70 8 2 10 //itemid 70 exists in delivery 2
72 12 1 0 //itemid 72 doesn't exists in other delivery of client 11
Since I need to add qtyOther to my existing qry i'm trying to avoid using Group By as it's a huge query and if I use SUM in select I will have to group by all items in select.
This is what I have so far:
Select ....., coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid) ,0) AS qtyOther
FROM B b
LEFT JOIN A a USING
LEFT JOIN (other tables)
WHERE clientid=10 ....
This query gives me the total sum of qty per itemid for specific clientid, regardless of which delivery it is. How do I change it so it will consider the delivryid? I need something like:
coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid) FROM B where deliveryid<>b.deliveryid ,0) AS qtyOther
Any suggestions how to do that?
Note: I can NOT change the condition in WHERE.
I think you just want to subtract out the total for the current delivery:
Select .....,
(coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid), 0) -
coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid, a.deliveryid), 0)
) as qtyOther