Select columns together with the sum() - sql

I have a problem in getting the columns and I also want to get the sum of total_amount.
CREATE TABLE purchase (
id int,
sheet_number varchar(255),
total_amount decimal(23,6),
transaction_status int
);
INSERT INTO purchase (id, sheet_number, total_amount, transaction_status)
VALUES (
'1', 'PO10010000001', '120.18', 1,
'2', 'PO10010000002', '87.23', 1,
'3', 'PO10010000003', '53.56', 3,
'4', 'PO10010000004', '150.28', 4,
'5', 'PO10010000005', '160.53' 3,
);
I want to get the columns and also the sum of this total_amount with respect (group by) of transaction_status.
I've created a SQL query like this but it doesn't work with the expected one.
Here is the SQL query that I've made:
SELECT
id,
sheet_number,
transaction_status,
sum(total_amount) AS total FROM purchase
GROUP BY transaction_status, id, sheet_number
I think the problem because I listed the other columns/attributes in the GROUP BY clause.
But I needed it because it will prompt an error message that the column is not valid since it is not contained in the group by clause.
The expected SQL query is like this (but I can't since there will be a prompt error):
SELECT
id,
sheet_number,
transaction_status,
sum(total_amount) AS total FROM purchase
GROUP BY transaction_status
The expected result will be:
[id],[sheet_number],[total],[transaction_status]
[1],[PO10010000001],[207.41],[1],
[2],[PO10010000002],[207.41],[1],
[3],[PO10010000003],[214.09‬],[3],
[4],[PO10010000004],[150.28],[4],
[5],[PO10010000005],[214.09‬],[3]
I just want to get all the same columns but I can get also the sum of total_amount.

You can use window function :
SELECT p.id, p.sheet_number, p.transaction_status,
SUM(p.total_amount) OVER (PARTITION BY p.transaction_status) AS total
FROM purchase p
ORDER BY p.id;

You can try the inner join to get the output as shown below.
Here I have taken total amount group by transaction status and done joining with actual table based on the transaction status column.
SELECT purchase.id
,purchase.sheet_number
,b.total AS total_amount
,purchase.transaction_status
FROM purchase
INNER JOIN (
SELECT transaction_status
,SUM(total_amount) AS total
FROM purchase
GROUP BY transaction_status
) b ON purchase.transaction_status = b.transaction_status
Here is the db<>fiddle demo.

Related

SQL Pivot column values

I have tried following this and this(SQL Server specific solution) but were not helpful.
I have two tables, Product and Sale and I want to find how many products are sold on each day. But I want to pivot the table so that columns become the products name and each row will contain the amount of products sold for each day ordered by the day.
Simplified schema is as following
CREATE TABLE product (
id integer,
name varchar(40),
price float(2)
);
CREATE TABLE sale(
id integer,
product_id integer,
transaction_time timestamp
);
This is what I want
I only managed to aggregate the total sales per day per product but I am not able to pivot the product names.
select date(sale.transaction_date)
, product.id
, product.name
, count(product_id)
from sale inner join
product on sale.product_id = product.id
group by date(sale.transaction_date)
, product.id
, product.name
This is the situation so far
Please suggest.
You need pivoting logic, e.g.
select
s.transaction_date::date,
count(case when p.name = 'intelligent_rubber_clock' then 1 end) as intelligent_rubber_clock,
count(case when p.name = 'intelligent_iron_wallet' then 1 end) as intelligent_iron_wallet,
count(case when p.name = 'practical_marble_car' then 1 end) as practical_marble_car
from sale s
inner join product p
on s.product_id = p.id
group by
s.transaction_date::date;
Since your expected output aggregates by date alone, then only the transaction date should be in your GROUP BY clause. The trick used here is to take the count of a CASE expression which returns 1 when the record is from a given product, and 0 otherwise. This generates conditional counts for each product, all in separate columns. To add more columns, just add more conditional counts.

How to get the sum of transaction amount happened in one date?

I am trying to write a query that will give me transaction amount sum happened in one date. The problem is , when I added column date in my query, I get individual values not their sum. The requirement for this query is to have one entry for each merchant but i am getting multiple rows for one merchant.
SELECT SUBSTR(m.MERCHANTLASTNAME, 1, 36) Name1,
m.MERCHANTBANKBSB MerchantAccbsb,
m.MERCHANTBANKACCNR Merchant_act,
m.MERCHANTID merchantid,
t.transactiondate date1,
sum(t.TRANSACTIONAMOUNT) as total
FROM fss_merchant m
JOIN fss_terminal term
ON m.MERCHANTID = term.MERCHANTID
JOIN FSS_DAILY_TRANSACTION t
ON term.TERMINALID = t.TERMINALID
group by t.transactiondate, SUBSTR(m.MERCHANTLASTNAME, 1, 36), m.MERCHANTID, m.MERCHANTBANKBSB, m.MERCHANTBANKACCNR,
m.MERCHANTLASTNAME
Output of my query:
I want to get one entry per each merchant with the sum of transaction amount in one day, not multiple rows of transaction in that day.
You can calculate the total amount in different inner query with the truncated date and join it with FSS_MERCHANT table so that issues described by #SatishSK and #mangusta is taken care.
You can use the following query:
SELECT
SUBSTR(M.MERCHANTLASTNAME, 1, 36) NAME1,
M.MERCHANTBANKBSB MERCHANTACCBSB,
M.MERCHANTBANKACCNR MERCHANT_ACT,
M.MERCHANTID MERCHANTID,
M_DATA.TRANSACTIONDATE DATE1,
M_DATA.TOTAL AS TOTAL
FROM
FSS_MERCHANT M
INNER JOIN (
SELECT
TERM.MERCHANTID MERCHANTID,
TRUNC(T.TRANSACTIONDATE) TRANSACTIONDATE,
SUM(T.TRANSACTIONAMOUNT) AS TOTAL
FROM
FSS_TERMINAL TERM
JOIN FSS_DAILY_TRANSACTION T ON TERM.TERMINALID = T.TERMINALID
GROUP BY
TERM.MERCHANTID,
TRUNC(T.TRANSACTIONDATE)
) M_DATA ON ( M.MERCHANTID = M_DATA.MERCHANTID );
Good luck!!
t.transactiondate column might contain date+time values. Use TRUNC(t.transactiondate) where you are using just t.transactiondate. You will get sum(transaction amount) "Date-wise" for each merchant.
OR
Filter out rows based on "Date" value in WHERE clause to retrieve data pertaining to a specific date.
Probably the reason is that you have included both m.MERCHANTLASTNAME and SUBSTR(m.MERCHANTLASTNAME,1,36) into the group by clause.
In case if there are entries with same SUBSTR(m.MERCHANTLASTNAME,1,36) but different m.MERCHANTLASTNAME, this is going to yield duplicates. You need to remove m.MERCHANTLASTNAME from group by clause

SQL Nested Select -Subquery returned more than 1 value-

I have a table Sales with columns SalesID, SalesName, SalesCity, SalesState.
I am trying to come up with a query that only shows salesName where there is one SalesName per SalesCity. So for example, if SaleA is in Houston and SaleB is in Houston, SaleA and SaleB will not be returned.
select
SalesName, SalesCity, SalesState
from
Sales
where
(select count(*) from Sales group by SalesCity) = 1;
I am not entirely sure how to link the inner select back out. I need another column in the nested select to identify the SalesID. I am currently stuck and have made no progress.
You can get the names of cities that have only 1 sale by using GROUP BY and HAVING operators. Then use these results in your where clause:
SELECT SalesName, SalesCity, SalesState
FROM Sales WHERE SalesCity IN
(
SELECT SalesCity
FROM Sales
GROUP BY SalesCity
HAVING COUNT(SalesCity) = 1
)
You can do this without a subquery:
select MIN(SalesName) as SalesName, SalesCity, MIN(SalesState) as SalesState
from Sales
group by SalesCity
having count(*) = 1;
If there is only one row for the city, then the min() will return the value on that row.

SQL: Using UNION

Here is the question and database info.
Use the UNION command to prepare a full statement for customer 'C001' - it should be laid out as follows. (Note that the values shown below are not correct.) You may be able to use '' or NULL for blank values - if necessary use 0.
Here is a link to the webpage with the database info. http://sqlzoo.net/5_0.htm or see the image below.
Here is what I have tried:
SELECT sdate AS LineDate, "delivery" AS LEGEND, price*quantity AS Total,"" AS Amount
FROM shipped
JOIN product ON (shipped.product=product.id)
WHERE badguy='C001'
UNION
SELECT rdate,notes, "",receipt.amount
FROM receipt
WHERE badguy='C001'
Here is what I get back:
Wrong Answer. The correct answer has 5 row(s).
The amounts don't seem right in the amount column and I can't figure out how to order the data by the date since it is using two different date columns (sdate and rdate which are UNIONED).
Looks like the data in the example is being aggregated by date and charge type using group by, that's why you are getting too many rows.
Also, you can sort by the alias of the column (LineDate) and the order by clause will apply to all the rows in the union.
SELECT sdate AS LineDate, "delivery" AS LEGEND, SUM(price*quantity) AS Total,"" AS Amount
FROM shipped
JOIN product ON (shipped.product=product.id)
WHERE badguy='C001'
GROUP BY sdate
UNION
SELECT rdate, notes, "",receipt.amount
FROM receipt
WHERE badguy='C001'
ORDER BY LineDate
It's usually easiest to develop each part of the union separately. Pay attention to the use of "null" to separate the monetary columns. The first select gets to name the columns.
select s.sdate as tr_date, 'Delivery' as type, sum((s.quantity * p.price)) as extended_price, null as amount
from shipped s
inner join product p on p.id = s.product
where badguy = 'C001'
group by s.sdate
union all
select rdate, notes, null, sum(amount)
from receipt
where badguy = 'C001'
group by rdate, notes
order by tr_date

how do i get the sum of the 4th column

this statement will generate a 4 column table:
SELECT shipped.badguy AS badguy, shipped.sdate AS LineDate,
'Delivery' AS Legend, -price*quantity AS amount
FROM product JOIN shipped ON (product.id = shipped.product)
UNION
SELECT receipt.badguy, receipt.rdate,notes, amount
FROM receipt
how do i get the total sum of the 4th of column of what the above generates?
I like to use subqueries for everything.
SELECT SUM(results.amount)
FROM
(
SELECT -price*quantity AS amount
FROM product JOIN shipped ON (product.id = shipped.product)
UNION
SELECT amount
FROM
...
) results
SUM(-price*quantity)
huh?
Try
sum(price*quantity)
or combine both query as
SELECT badguy,rdate,notes,SUM(AMOUNT) FROM(
SELECT shipped.badguy AS badguy, shipped.sdate AS LineDate,
'Delivery' AS Legend, -price*quantity AS amount
FROM product JOIN shipped ON (product.id = shipped.product)
UNION
SELECT receipt.badguy, receipt.rdate,notes, amount
FROM) A
Wrap your query in another query, where the outer query just gets the sum you want. This makes your query a subquery.
SELECT SUM(amount) FROM (
SELECT shipped.badguy AS badguy, shipped.sdate AS LineDate,
'Delivery' AS Legend, -price*quantity AS amount
FROM product JOIN shipped ON (product.id = shipped.product)
UNION
SELECT receipt.badguy, receipt.rdate,notes, amount
FROM <...>
)