How do I 'subtract' sql tables?
The set operation you are looking for is called MINUS, but in SQL Server the keyword is EXCEPT
SELECT ... // all documents
EXCEPT
SELECT ... // active documents
I believe that the EXCEPT set operation became available in SQL Server 2005.
sql - subtract values from different tables
You can directly perform operations on multiple columns and show that result in a new column which you can name using as
clause. You can perform join to do operation between two columns of different tables in a similar fashion. To answer your question, following is the SQL query:
SELECT a.id, a.amount-b.amount as Difference FROM table1 a
INNER JOIN table2 b
ON a.id=b.id
How to subtract values generated from two tables?
You can use cross join
:
select n.nov_sum - o.oct_sum as REVENUE_DIFF
from (select sum(n.price) as nov_sum
from nov_data_part n
where event_type = 'purchase'
) n cross join
(select sum(o.price) as oct_sum
from oct_data_part n
where event_type = 'purchase'
) o;
As a note: You have a real problem with your data model if you are splitting rows across different tables based on the month.
Subtraction value with same table
I am going to assume that you have another column which tells you the order in which the qty
should be subtracted from the order
column and have called this the datetime
column (but you can use whatever column you have available to provide a deterministic ordering of the rows). Given that, you can calculate the value
using an analytic SUM
function:
SELECT id,
cust,
datetime,
order_total,
qty,
order_total
- SUM( COALESCE( qty, 0 ) )
OVER ( PARTITION BY id, cust, order_total ORDER BY datetime )
AS value
FROM table_name
Which, for the sample data:
CREATE TABLE table_name ( id, cust, datetime, order_total, qty ) AS
SELECT '0001', 'abc', DATE '2021-01-01', 10000, 2000 FROM DUAL UNION ALL
SELECT '0001', 'abc', DATE '2021-01-02', 10000, 4000 FROM DUAL UNION ALL
SELECT '0001', 'abc', DATE '2021-01-03', 10000, 4000 FROM DUAL UNION ALL
SELECT '0002', 'bcd', DATE '2021-01-01', 5000, 2000 FROM DUAL UNION ALL
SELECT '0003', 'fgh', DATE '2021-01-01', 3000, 1000 FROM DUAL UNION ALL
SELECT '0004', 'ghj', DATE '2021-01-01', 5000, NULL FROM DUAL;
Outputs:
ID | CUST | DATETIME | ORDER_TOTAL | QTY | VALUE
:--- | :--- | :-------- | ----------: | ---: | ----:
0001 | abc | 01-JAN-21 | 10000 | 2000 | 8000
0001 | abc | 02-JAN-21 | 10000 | 4000 | 4000
0001 | abc | 03-JAN-21 | 10000 | 4000 | 0
0002 | bcd | 01-JAN-21 | 5000 | 2000 | 3000
0003 | fgh | 01-JAN-21 | 3000 | 1000 | 2000
0004 | ghj | 01-JAN-21 | 5000 | null | 5000
db<>fiddle here
How to subtract values from different tables?
You can do this with a CTE or with subqueries.
Using a CTE:
WITH tbla AS (
SELECT COUNT(A.Id) A
FROM Table_A AS A
WHERE A.City = 'NewYork'
),
tblb AS (
SELECT COUNT(B.Id) B
FROM Table_B AS B
WHERE B.City = 'England'
),
tblc AS (
SELECT COUNT(C.Id) C
FROM Table_C AS C
WHERE C.City = 'Berlin'
)
SELECT a.A - b.B - c.C
FROM tbla a
CROSS JOIN tblb b
CROSS JOIN tblc c;
Same thing only with subqueries
SELECT a.A - b.B - c.C
FROM (
SELECT COUNT(A.Id) A
FROM Table_A AS A
WHERE A.City = 'NewYork'
) a
CROSS JOIN (
SELECT COUNT(B.Id) B
FROM Table_B AS B
WHERE B.City = 'England'
) b
CROSS JOIN (
SELECT COUNT(C.Id) C
FROM Table_C AS C
WHERE C.City = 'Berlin'
) c;
Note: I removed the WITH (NOLOCK)
hints because in all likelihood they are not needed in this case.
Subtract one table from another
Basically FYI If A={A,A,O},B={A,P}
then A-B
is logically
select * from t1 except select * from t2
try this !
create table #t(id varchar(10))
create table #t1(id1 varchar(10))
insert into #t values('apple'),('apple'),('orange')
insert into #t1 values('apple'),('pear')
select * from
(
select *,rn=row_number()over(partition by id order by id) from #t
except
select *,rn1=row_number()over(partition by id1 order by id1) from #t1
)x
SEE DEMO
SQL Subtract two columns on different tables
Use a derived table for the invoice amount SUM()
, then JOIN
back to Customer:
DECLARE @CreditRemaining INT
SELECT @CreditRemaining = (c.CreditLimit - TotalSpent)
FROM Customer c
INNER JOIN (SELECT SUM(Amount) TotalSpent, CustomerID
FROM Invoices
GROUP BY CustomerID) i ON i.CustomerID = c.ID
As others mentioned, this is assuming you are limiting your selection to one customer.
For all customers, just use a select:
SELECT C.Name, (c.CreditLimit - TotalSpent) CreditRemaining
FROM Customer c
INNER JOIN (SELECT SUM(Amount) TotalSpent, CustomerID
FROM Invoices
GROUP BY CustomerID) i ON i.CustomerID = c.ID
GROUP BY C.Name
Subtraction of counts of 2 tables
The potential issue here is that for any week you might only have additions or removals, so to align a count from the 2 tables - by week - an approach would be to use a full outer join, like this:
SELECT COALESECE(A.week, b.week) as week
, count_a
, count_b
, COALESECE(count_a,0) - COALESECE(count_b,0) net
FROM (
SELECT DATE_TRUNC('week', TIMESTAMP AT time ZONE '+08') AS week
, Count(*) AS count_A
FROM table_a
GROUP BY DATE_TRUNC('week', TIMESTAMP AT time ZONE '+08')
) a
FUUL OUTER JOIN (
SELECT DATE_TRUNC('week', TIMESTAMP AT time ZONE '+08') AS week
, Count(*) AS count_b
FROM table_b
GROUP BY DATE_TRUNC('week', TIMESTAMP AT time ZONE '+08')
) b on a.week = b.week
Related Topics
How to Set Isolation Level on SQLcommand/Sqlconnection Initialized with No Transaction
Sql: Many-To-Many Table and Query
When Are Database Triggers Bad
How to Find Out Whether a Table Has Some Unique Columns
Workaround for Ora-00997: Illegal Use of Long Datatype
Issues with SQL Comparison and Null Values
SQL Comma Delimted Column => to Rows Then Sum Totals
Oracle Autoincrement with Sequence and Trigger Is Not Working Correctly
List All Tables in Postgresql Information_Schema
How to Get a Plain Text Postgres Database Dump on Heroku
How to Pass Parameter in Ado.Net Source Ssis
Sql: Group by on Consecutive Records
Active Directory Data into SQL Table
Best to Use * When Calling a Lot of Fields in MySQL
SQL Oracle Left Join and Subquery Error: Ora-00905: Missing Keyword
Oracle SQL Comparison of Dates Returns Wrong Result
How to Remove Duplicates from Space Separated List by Oracle Regexp_Replace