sql - getting sum of same column from multiple tables - sql

I have a few tables in my DB. Let's call them table1, table2, table3.
All of them have a column named value.
I need to create a query that will return a single number, where this number is the sum of all the value columns from all the tables together...
I've tried the following way:
SELECT (SELECT SUM(value) FROM table1) + (SELECT SUM(value) FROM table2) + (SELECT SUM(value) FROM table3) as total_sum
But when at least one of the inner SUM is NULL, the entire total value (total_sum here) is NULL, so that's not very trustworthy.
When there is no value in a certain inner SUM query, I need it to return 0, so it doesn't affect the rest of the SUM.
To make it more clear, let's say I have the following 2 tables:
TABLE1:
ID | NAME | VALUE
1 Name1 1000
2 Name2 2000
3 Name3 3000
TABLE2:
ID | NAME | VALUE
1 Name1 1500
2 Name2 2500
3 Name3 3500
Eventually, the query I need will return a single value - 13500, which is the total sum of all the values under the VALUE column of all the tables here.
All the other columns have no meaning for the needed query, and I even don't care much for performance in this case.

You can achieve it using Coalesce as follows
SELECT
(SELECT coalesce(SUM(value),0) FROM table1) +
(SELECT coalesce(SUM(value),0) FROM table2) +
(SELECT coalesce(SUM(value),0) FROM table3) as total_sum
Another approach is to use union all to merge all values into single table
select distinct coalesce(sum(a.value), 0) as total_sum from
(select value from table1
union all
select value from table 2
union all
select value from table 3) a;

You can use the ISNULL function to take care of the NULLs.
SELECT ISNULL((
SELECT SUM(value) FROM table1
)
, 0
) + ISNULL((
SELECT SUM(value) FROM table2
)
, 0
) + ISNULL((
SELECT SUM(value) FROM table3
)
, 0
) AS total_sum;

You could simply sum all of them:
select sum(total) as Total
from (
select sum(value) as total from Table1
union all
select sum(value) as total from Table2
union all
select sum(value) as total from Table3
) t;

Related

SQL Inner join with sum and null value

The table below is an extract of a larger set of data
In my scenario Column 2 is null when is the "parent" record (Column 1 = AB1 and Column 2 is NULL) and as you can see the following 2 "child" records under Column 2 have AB1 as identifier which matches the AB1 from Column 1, what I want to do is to sum the values on Column 3 when Column 2 has the same identifier (AB1), up to this point the sum = 29 (for this case I can do a SUM and group by AB1). My issue arises when I need to add the value of 10 in Column 3 when column 2 is NULL and Column 1 is AB1 (parent identifier). The common identifier is AB1 but for the parent record the identifier is in Column 1 instead of Column 2. I need a SQL that return a total sum of 39.
Edit:
Thanks for the prompt responses, my apologies I think my question was not clear enough. I am using MS SQL Server Management Studio
The goal for the query to sum the amounts on Column 3 by grouping by the records on Column 2 that have the same identifier (AB1) and then find that same identifier on Column 1 (AB1) and also add that value to the total sum.
The query below is doing the group by Column 2 correctly because for example if I have 10 records with the identifier AB1 it is returning one row with the sum of the amounts on Column 3, the issue is that I also need to add to that sum when the identifier AB1 is also in Column 1.
select t1.Column1 , round(sum (t1.Column3),2) as Total from table t1, table t2 where
and t1.Column2 = t2. Column1 group by t1. Column2
Basically this table stores transactions and the initial transaction “parent” is in Column 1 (AB1) and all other transactions “children” linked to the parent transaction have that identifier (AB1) but in Column 2. Column 1 is a unique identifier and does not repeat and then is the “parent” transaction it is NULL on Column 2 but that identifier (AB1) can be repeated multiple times in Column 2 depending all the “children” transactions that are linked to the “parent”.
Oracle
The WITH clause is here just to generate sample data and, as such, it is not the part of the answer.
I don't know what is the expected result, but the Totals could be calculated using Union All (without Inner Join)
WITH
tbl AS
(
Select 'AB1' "COL_1", Null "COL_2", 10 "COL_3" From Dual Union All
Select 'CD2' "COL_1", 'AB1' "COL_2", 15 "COL_3" From Dual Union All
Select 'EF3' "COL_1", 'AB1' "COL_2", 14 "COL_3" From Dual
)
SELECT
ID, Sum(TOTAL) "TOTAL"
FROM
(
SELECT COL_1 "ID", Sum(COL_3) "TOTAL" FROM tbl GROUP BY COL_1 UNION ALL
SELECT COL_2 "ID", Sum(COL_3) "TOTAL" FROM tbl GROUP BY COL_2
)
WHERE ID Is Not Null
GROUP BY ID
ORDER BY ID
--
-- R e s u l t
--
ID TOTAL
--- ----------
AB1 39
CD2 15
EF3 14
It is a Sum() Group By aggregation, but the same result gives Sum() analytic function with DISTINCT keyword.
SELECT DISTINCT
ID, Sum(TOTAL) OVER(PARTITION BY ID ORDER BY ID) "TOTAL"
FROM
(
SELECT COL_1 "ID", Sum(COL_3) "TOTAL" FROM tbl GROUP BY COL_1 UNION ALL
SELECT COL_2 "ID", Sum(COL_3) "TOTAL" FROM tbl GROUP BY COL_2
)
WHERE ID Is Not Null
--
-- R e s u l t
--
ID TOTAL
--- ----------
AB1 39
CD2 15
EF3 14
And if you need Inner Join then the answer is below. Note that there is only ID which actually has children. That is because of the Inner Join. Regards...
SELECT
t1.COL_1 "ID",
Max(t1.COL_3) + Sum(t2.COL_3) "TOTAL"
FROM
tbl t1
INNER JOIN
tbl t2 ON (t2.COL_2 = t1.COL_1)
GROUP BY t1.COL_1
ORDER BY t1.COL_1
--
-- R e s u l t
--
ID TOTAL
--- ----------
AB1 39
select sum(Column3)
from TheTable
where 'AB1' in (Column1, Column2);
will sum the value of Column3 for the parent (Column1 = 'AB1') and the children (Column2 = 'AB1').
If the parent-child hierarchy has more than two levels, and you want to sum Column3 for grandchildren, grand-grandchildren, and so on, you can use a hierarchical query (also known as a recursive query). The exact syntax depends on your database, this is for PostgreSQL:
with recursive Hier(Column1, Column2, Column3) as
(
select Column1, Column2, Column3
from TheTable
where Column1 = 'AB1'
union all
select t.Column1, t.Column2, t.Column3
from TheTable t
join Hier h on t.Column2 = h.Column1
)
select sum(Column3)
from Hier;
You can spilt the two sets of data then union them together. From there it will be a simple sum group by.
To do this we simply saying
take Column1 as the Parent if Column2 IS null
take Column2 as the Parent if Column2 IS not null
Select Column1 as Parent, Column3
from TheTable
where Column2 IS null
Union
Select Column2 as Parent, Column3
from TheTable
where Column2 IS not null
From there you can use this as a cte
WITH data AS
(
Select Column1 as Parent, Column3
from TheTable
where Column2 IS null
Union
Select Column2 as Parent, Column3
from TheTable
where Column2 IS not null)
Select Parent, Sum(Column3)
from Data
Group by Parent
Result will be
Parent SumColumn3
AB1 39

SQL Joining two tables and removing the duplicates from the two tables but without loosing any duplicates from the tables itslef

I want to join two tables and remove duplicates from both the tables but keeping any duplicate value found in the first table.
T1
Name
-----
A
A
B
C
T2
Name
----
A
D
E
Expected result
A - > FROM T1
A - > FROM T1
B
C
D
E
I tried union but removes all duplicates of 'A' from both tables.
How can I achieve this?
Filter T2 before UNION ALL
select col
from T1
union all
select col
from T2
where not exists (select 1 from T1 where T1.col = T2.col)
Assuming you want the number of duplicates from the table with the most repetitions for each value, you can do it with the ROW_NUMBER() windowing function, to eliminate duplicates by their sequence with the set of repetitions in each table.
SELECT Name FROM (
SELECT Name, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Name ) AS Row
FROM T1
UNION
SELECT Name, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Name ) AS Row
FROM T2
) x
ORDER BY Name
To see how this works out, we add two B rows to T2 then do this:
SELECT Name, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Name ) AS Row
FROM T1
Name Row
A 1
A 2
B 1
C 1
SELECT Name, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Name ) AS Row
FROM T2
Name Row
A 1
B 1
B 2
D 1
E 1
Now UNION them without ALL to combine and eliminate duplicates:
SELECT Name, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Name ) AS Row
FROM T1
UNION
SELECT Name, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Name ) AS Row
FROM T2
Name Row
A 1
A 2
B 1
B 2
C 1
D 1
E 1
The final query up top is then just eliminating the Row column and sorting the result, to ensure ascending order.
See SQL Fiddle for demo.
select * from T1
union all
select * from T2 where name not in (select distinct name from T1)
Sql Fiddle Demo
you should use "union all" instead of "union".
"union" remove other duplicated records while "union all" gives all of them.
for you result,because of we filtered intersects from table 2 in "where",we don't need "UNION ALL"
select col1 from t1
union
select col1 from t2 where t2.col1 not in(select t1.col1 from t1)
I D'not know the following code is good practice or not But it's working
select name from T1
UNION
select name from T2 Where name not in (select name from T1)
The Above Query Filter the value based on T1 value and then join two tables values and show the result.
I hope it's helps you thanks.
Note : It's not better way to get result it's affect your performance.
I sure i update the better solution after my research
You want all names from T1 and all names from T2 except the names that are in T1.
So you can use UNION ALL for the 2 cases and the operator EXCEPT to filter the rows of T2:
SELECT Name FROM T1
UNION ALL
(
SELECT Name FROM T2
EXCEPT
SELECT Name FROM T1
)
See the demo.
Results:
> | Name |
> | :--- |
> | A |
> | A |
> | B |
> | C |
> | D |
> | E |

Find the unique value in column MS SQL database

I have a set of data as below
number quantity
1 4
2 6
3 7
4 9
2 1
1 2
5 4
I need to find the unique value in the column "number"
The output should look like this:
number quantity
3 7
4 9
5 4
Any help would be appreciated. I am using MS SQL
In the inner query get all the distinct numbers, then join with again with the main table to get your expected results.
select o.*
from mytable o , (select number
from mytable
group by number) dist
where o.number = dist.number
One way to go could be to have an aggregate query that counts the number of occurrences for each number use it in a subquery:
SELECT number, quantity
FROM my_table
WHERE number IN (SELECT number
FROM my_table
GROUP BY number
HAVING COUNT(*) = 1)
If your column name is my_column in table my_table, the query is:
SELECT my_column, COUNT(*) as count
FROM my_table
GROUP BY my_column
HAVING COUNT(*) > 1
This will return all records that have duplicate my_column content, as well as how many times this content occurs in the database.
you can use below code for desire output:
SELECT DISTINCT(my_column), COUNT(*) as count
FROM my_table
GROUP BY my_column
Try this :
SELECT *
FROM yourtable t1
WHERE (SELECT Count(*)
FROM yourtable t2
WHERE t1.number = t2.number) = 1
Query in where clause will return number of occurrences of each number and checking it with 1 will return only those rows will have only one occurrence in table.
You can probably use ROW_NUMBER() analytic function like
select * from
(
select number,
quantity,
ROW_NUMBER() OVER(PARTITION BY number ORDER BY number) AS rn
from table1
) tab where rn = 1;
Try this:
create table #TableName(number int, quantity int)
insert into #TableName values(1, 2)
insert into #TableName values(1, 4)
insert into #TableName values(2, 4)
SELECT number, quantity
FROM #TableName
WHERE number
IN(SELECT number
FROM #TableName
GROUP BY number
HAVING COUNT(NUMBER) = 1)

How can I get the count of multiple columns in SQL

Say I had two tables in SQL. Now I would like to get the quotient of the count of table 1 and count of table 2. How can I do that?
In Short:
(# of rows in table 1) / (# of rows in table 2)
EDIT:
This is what I tried:
SELECT COUNT(t1.a) / COUNT(t2.a)
FROM table1 t1, table2 t2
Here's one way to get the result:
SELECT c1.cnt / c2.cnt AS q
FROM ( SELECT COUNT(1) AS cnt
FROM table1
) c1
CROSS
JOIN ( SELECT COUNT(1) AS cnt
FROM table2
) c2
Another way to get an equivalent result:
SELECT (SELECT COUNT(1) FROM table1) / (SELECT COUNT(1) FROM table2) AS q
I would prefer the first query if I also needed to return the counts from the tables as separate columns in the resultset, for example:
SELECT c1.cnt AS table1_count
, c2.cnt AS table2_count
, c1.cnt / c2.cnt AS q
FROM ...
Try this:
SELECT COUNT(table1.column) as 'Table 1 Count'
,COUNT(table2.column) as 'Table 2 Count'
,COUNT(table1.column) / COUNT(table2.column) as 'Quotient'
FROM table1, table2
with
Ctable1 as
(select count(*) as num1 from table1),
Ctable2 as
(select count(*) as num2 from table2)
select num1 / num2 as quotient
from Ctable1,Ctable2
Remember:
When you count column, rows with "NULL" data will NOT count. (If you use Oracle, you can use count(a.*)
Int division in sql like most languages, returns int. (5/2 = 2 and not 2.5).

Duplicate Counts - TSQL

I want to get All records that has duplicate values for SOME of the fields (i.e. Key columns).
My code:
CREATE TABLE #TEMP (ID int, Descp varchar(5), Extra varchar(6))
INSERT INTO #Temp
SELECT 1,'One','Extra1'
UNION ALL
SELECT 2,'Two','Extra2'
UNION ALL
SELECT 3,'Three','Extra3'
UNION ALL
SELECT 1,'One','Extra4'
SELECT ID, Descp, Extra FROM #TEMP
;WITH Temp_CTE AS
(SELECT *
, ROW_NUMBER() OVER (PARTITION BY ID, Descp ORDER BY (SELECT 0))
AS DuplicateRowNumber
FROM #TEMP
)
SELECT * FROM Temp_cte
DROP TABLE #TEMP
The last column tells me how many times each row has appeared based on ID and Descp values.
I want that row but I ALSO need another column* that indicates both rows for ID = 1 and Descp = 'One' has showed up more than once.
So an extra column* (i.e. MultipleOccurances (bool)) which has 1 for two rows with ID = 1 and Descp = 'One' and 0 for other rows as they are only showing up once.
How can I achieve that? (I want to avoid using Count(1)>1 or something if possible.
Edit:
Desired output:
ID Descp Extra DuplicateRowNumber IsMultiple
1 One Extra1 1 1
1 One Extra4 2 1
2 Two Extra2 1 0
3 Three Extra3 1 0
SQL Fiddle
You say "I want to avoid using Count" but it is probably the best way. It uses the partitioning you already have on the row_number
SELECT *,
ROW_NUMBER() OVER (PARTITION BY ID, Descp
ORDER BY (SELECT 0)) AS DuplicateRowNumber,
CASE
WHEN COUNT(*) OVER (PARTITION BY ID, Descp) > 1 THEN 1
ELSE 0
END AS IsMultiple
FROM #Temp
And the execution plan just shows a single sort
Well, I have this solution, but using a Count...
SELECT T1.*,
ROW_NUMBER() OVER (PARTITION BY T1.ID, T1.Descp ORDER BY (SELECT 0)) AS DuplicateRowNumber,
CASE WHEN T2.C = 1 THEN 0 ELSE 1 END MultipleOcurrences FROM #temp T1
INNER JOIN
(SELECT ID, Descp, COUNT(1) C FROM #TEMP GROUP BY ID, Descp) T2
ON T1.ID = T2.ID AND T1.Descp = T2.Descp