Displaying unique attributes of table and the total value in postgresql - sql

I have one table with columns stamp_type and amount as follows
stamp_type | amount
--------------------------------------------------------------+--------
GENERAL STAMP | 11000
GENERAL STAMP | 25000
COURT FEE STAMP | 9800
SPECIAL ADHESIVE | 721000
GENERAL STAMP | 125000
COURT FEE STAMP | 21000
Now I want to display as follows:
stamp_type | amount
GENERAL STAMP 161000
COURT FEE STAMP 30800
SPECIAL ADHESIVE 721000
TOTAL:912800
I am unable to display the unique values. can any one give suggest me the query. I tried to use Distinct but dint work.

select * from
(
select 0 as srt, stamp_type, sum(amount) as SumAmount from t group by stamp_type
union
select 1 as srt, 'Total' as stamp_type, sum(amount) as SumAmount from t
) b order by srt

try this code::
select stamp_type, sum(amount) amount
from tbl
group by stamp_type
union
select 'Total:' stamp_type,sum(amount) amount
from tbl;

Related

How to calculate average monthly number of some action in some perdion in Teradata SQL?

I have table in Teradata SQL like below:
ID trans_date
------------------------
123 | 2021-01-01
887 | 2021-01-15
123 | 2021-02-10
45 | 2021-03-11
789 | 2021-10-01
45 | 2021-09-02
And I need to calculate average monthly number of transactions made by customers in a period between 2021-01-01 and 2021-09-01, so client with "ID" = 789 will not be calculated because he made transaction later.
In the first month (01) were 2 transactions
In the second month was 1 transaction
In the third month was 1 transaction
In the nineth month was 1 transactions
So the result should be (2+1+1+1) / 4 = 1.25, isn't is ?
How can I calculate it in Teradata SQL? Of course I showed you sample of my data.
SELECT ID, AVG(txns) FROM
(SELECT ID, TRUNC(trans_date,'MON') as mth, COUNT(*) as txns
FROM mytable
-- WHERE condition matches the question but likely want to
-- use end date 2021-09-30 or use mth instead of trans_date
WHERE trans_date BETWEEN date'2021-01-01' and date'2021-09-01'
GROUP BY id, mth) mth_txn
GROUP BY id;
Your logic translated to SQL:
--(2+1+1+1) / 4
SELECT id, COUNT(*) / COUNT(DISTINCT TRUNC(trans_date,'MON')) AS avg_tx
FROM mytable
WHERE trans_date BETWEEN date'2021-01-01' and date'2021-09-01'
GROUP BY id;
You should compare to Fred's answer to see which is more efficent on your data.

How to make accounting balance report?

I'm new to Oracle apex and SQL. I am developing an Oracle app for accounting. My table ga_voucher contains the following columns with values like:
VNO | DBIT CODE | AMOUNT | CREDIT CODE | VDATE | NARRATION
01 121005 40000 331001 09/07/2021 ABCD
02 331002 50000 121005 09/07/2021
I want to generate report with unique account code balance (debit total of a code - credit total) like:
Account CODE | DEBIT TOTAL|CREDIT TOTAL | BALANCE
331002 50000 | 40000 | 10000
What is the SQL query for the report? Please help me.
I'm pretty sure the 331001 in the first row should really be 331002. If so, I think you want to unpivot the data and aggregate:
select x.account_code, sum(x.debit) as debit, sum(x.credit) as credit,
sum(x.debit - x.credit) as balance\
from ga_voucher v cross join lateral
(select v.debit_code as account_code, v.amount as debit, 0 as credit from dual union all
select v.credit_code, 0, v.amount from dual
) x
group by x.account_code;

Cumulative Sum Query in SQL table with distinct elements

I have a table like this, with column names as Date of Sale and insurance Salesman Names -
Date of Sale | Salesman Name | Sale Amount
2021-03-01 | Jack | 40
2021-03-02 | Mark | 60
2021-03-03 | Sam | 30
2021-03-03 | Mark | 70
2021-03-02 | Sam | 100
I want to do a group by, using the date of sale. The next column should display the cumulative count of the sellers who have made the sale till that date. But same sellers shouldn't be considered again.
For example,
The following table is incorrect,
Date of Sale | Count(Salesman Name) | Sum(Sale Amount)
2021-03-01 | 1 | 40
2021-03-02 | 3 | 200
2021-03-03 | 5 | 300
The following table is correct,
Date of Sale | Count(Salesman Name) | Sum(Sale Amount)
2021-03-01 | 1 | 40
2021-03-02 | 3 | 200
2021-03-03 | 3 | 300
I am not sure how to frame the SQL query, because there are two conditions involved here, cumulative count while ignoring the duplicates. I think the OVER clause along with the unbounded row preceding may be of some use here? Request your help
Edit - I have added the Sale Amount as a column. I need the cumulative sum for the Sales Amount also. But in this case , all the sale amounts should be considered unlike the salesman name case where only unique names were being considered.
One approach uses a self join and aggregation:
WITH cte AS (
SELECT t1.SaleDate,
COUNT(CASE WHEN t2.Salesman IS NULL THEN 1 END) AS cnt,
SUM(t1.SaleAmount) AS amt
FROM yourTable t1
LEFT JOIN yourTable t2
ON t2.Salesman = t1.Saleman AND
t2.SaleDate < t1.SaleDate
GROUP BY t1.SaleDate
)
SELECT
SaleDate,
SUM(cnt) OVER (ORDER BY SaleDate) AS NumSalesman,
SUM(amt) OVER (ORDER BY SaleDate) AS TotalAmount
FROM cte
ORDER BY SaleDate;
The logic in the CTE is that we try to find, for each salesman, an earlier record for the same salesman. If we can't find such a record, then we assume the record in question is the first appearance. Then we aggregate by date to get the counts per day, and finally take a rolling sum of counts in the outer query.
The best way to do this uses window functions to determine the first time a sales person appears. Then, you just want cumulative sums:
select saledate,
sum(case when seqnum = 1 then 1 else 0 end) over (order by saledate) as num_salespersons,
sum(sum(sales)) over (order by saledate) as running_sales
from (select t.*,
row_number() over (partition by salesperson order by saledate) as seqnum
from t
) t
group by saledate
order by saledate;
Note that this in addition to being more concise, this should have much, much better performance than a solution that uses a self-join.

postgresql - how to calculate the percentage of number of entries in one table w.r.t to no of entries in another table

I have two tables(A & B) in my database(c). both tables contains two coulmns as shown below
column name Datatype
eventtime timestamp without time zone
serialnumber numeric
Table A contains total number of products (good and downgraded -- but in these table they are not defined as affected/downgraded) produced in each day. And table B contains total number of only downgraded products.
I want to make an quality process control chart using the percentage of downgraded products w.r.t total number of products produced (using serialnumber to join for example).
could some one tell me how can i get the percentage value for each day (also for each hour)
Use date_trunc() to group rows by desired period, e.g.:
select
a.r_date::date date,
downgraded,
total,
round(downgraded::numeric/total* 100, 2) percentage
from (
select date_trunc('day', eventtime) r_date, count(*) downgraded
from b
group by 1
) b
join (
select date_trunc('day', eventtime) r_date, count(*) total
from a
group by 1
) a
using (r_date)
order by 1;
date | downgraded | total | percentage
------------+------------+-------+------------
2015-05-05 | 3 | 4 | 75.00
2015-05-06 | 1 | 4 | 25.00
(2 rows)

Get max of column using sum

I have one table with following data..
saleId amount date
-------------------------
1 2000 10/10/2012
2 3000 12/10/2012
3 2000 11/12/2012
2 3000 12/10/2012
1 4000 11/10/2012
4 6000 10/10/2012
From my table I want result with max of sum amount between dates 10/10/2012 and 12/10/2012 which for the data above will be:
saleId amount
---------------
1 6000
2 6000
4 6000
Here 6000 is the max of the sums (by saleId) so I want ids 1, 2 and 4.
You have to use Sub-queries like this:
SELECT saleId , SUM(amount) AS Amount
FROM Table1
GROUP BY saleId
HAVING SUM(amount) =
(
SELECT MAX(AMOUNT) FROM
(
SELECT SUM(amount) AS AMOUNT FROM Table1
WHERE date BETWEEN '10/10/2012' AND '12/10/2012'
GROUP BY saleId
) AS A
)
See this SQLFiddle
This query goes through the table only once and is fairly optimised.
select top(1) with ties saleid, amount
from (
select saleid, sum(amount) amount
from tbl
where date between '20121010' and '20121210'
group by saleid
) x
order by amount desc;
You can produce the SUM with the WHERE clause as a derived table, then SELECT TOP(1) in the query using WITH TIES to show all the ones with the same (MAX) amount.
When presenting dates to SQL Server, try to always use the format YYYYMMDD for robustness.