How to SUM via Group By? - sql

I have a table something like this:
ID Marks Weightatthistime
1 5 44
1 5 43
1 5 41
2 4 39
2 4 38
I want the total marks obtained by the IDs, so I want my query to return: 9.
I know I could do a:
select ID, sum(Marks) from table group by 1
but I simply just want the total sum and not another mini table. The table is aggregated at this level and there's no way for me to change it.

Use subquery :
select id, sum(marks)
from (select distinct id, marks
from table t
) t
group by id;
If you want only sum then use only sum(marks) :
select sum(marks)
from (select distinct id, marks
from table t
) t;

use distinct
select sum( distinct Marks) from table
with cte as
(
select 1 id, 5 as m union all
select 1,5 union all
select 1,5 union all
select 2,4 union all
select 2,4
) select sum(distinct m) from cte
but if multiple user have same number then follow subquery method that #Yogesh shown
output
9

I believe this should work with any ANSI SQL engine.
Select ID, Marks, Weightatthistime, (Select Sum(Marks) From Table1) SumAllMarks
From Table1
This will put 9 on each record.

SELECT sum(DISTINCT marks) FROM table;
You can use this query to get the sum of the distinct mark values.

Related

oracle count query with union

I have a query with union all functionality each giving me count(*) return from respective queries and another count query like below. I want an outer query that gives the total.
1st query
select count(*) from a
union all
select count(*) from b;
Sample result for 1st query:
COUNT
10
40
2nd query
select count(*) from xy;
Sample result for 2nd query:
COUNT
20
I want output like this in 2 rows:
TABLES
COUNT
xy
20
ab
50
something like above. How can I achieve this in oracle? please suggest the best way to do this.
I wrote a select and union all but not sure how to proceed further.
One option is to sum counts returned by the 1st query and then union it with the 2nd; also, add constants which show the source:
select 'ab' what, (select count(*) from a) + (select count(*) from b) cnt from dual
union all
select 'xy', count(*) from xy;
You can use:
SELECT 'ab' AS type,
COUNT(*) AS total
FROM ( SELECT 1 FROM a UNION ALL
SELECT 1 from b );
UNION ALL
SELECT 'xy', COUNT(*)
FROM xy;
You can sum counts from your three unioned Select statements and group the result by combination of sources:
WITH
a AS
( Select LEVEL "A_ID", 'some column a' "COL_A" From Dual Connect By LEVEL <= 30 ),
b AS
( Select LEVEL "B_ID", 'some column b' "COL_B" From Dual Connect By LEVEL <= 20 ),
xy AS
( Select LEVEL "XY_ID", 'some column xy' "COL_XY" From Dual Connect By LEVEL <= 20 )
with above sample data it is like here:
SELECT
CASE WHEN SOURCE IN('a', 'b') THEN 'ab' ELSE SOURCE END "SOURCE",
Sum(CNT) "CNT"
FROM
( Select 'a' "SOURCE", Count(*) "CNT" From a Union All
Select 'b', Count(*) From b Union All
Select 'xy', Count(*) From xy
)
GROUP BY
CASE WHEN SOURCE IN('a', 'b') THEN 'ab' ELSE SOURCE END
--
-- R e s u l t :
-- SOURCE CNT
-- ------ ----------
-- ab 50
-- xy 20
Assuming that your real queries can be a lot more complex, I take it as a given that we shall not try to change them and somehow merge or split them.
Your first query returns two rows. You want to get their sum, so you must aggregate the result and use SUM.
Below query uses CTEs (subqueries in the WITH clause) for your two queries, and then a query that gets this sum. It then uses these CTEs for the final UNION ALL query.
with query1 (cnt) as (select count(*) from a union all select count(*) from b)
, query2 (cnt) as (select count(*) from xy)
, sumquery1 (total) as (select sum(cnt) from query1)
select 'ab' as tables, total from sumquery1
union all
select 'xy' as tables, cnt from query2
order by tables desc;

how to repeat each row twice

I have a requirement for a report and I would like my sql query to repeat each row twice.
Example :
**Table 1**
Id Name
1 Ab
2 Cd
3 Ef
I want to write a query which outputs the following :
1 Ab
1 Ab
2 Cd
2 Cd
3 Ef
3 Ef
Is there a way I can do it ?
I cannot think of anything except using union
Select Id, name from Table1 union select Id, name from Table1
You can use a union all. A union will not work, because it will eliminate duplicates. Another way is a cross join:
select id, name
from table1 t1 cross join
(select 1 as n union all select 2) n;
You can also use UNION ALL, put them under CTE (Common Table Expression) and Order By Id:
WITH CTE AS
(
SELECT Id, Name FROM Table_1
UNION ALL
SELECT Id, Name FROM Table_1
)
SELECT Id, Name
FROM CTE
ORDER BY Id;
As this will reorder them and stacked them as duplicates
Solution will be like this:
select Id, name from Table1
union all
select Id, name from Table1

SQL Query, Union Order by like a tree

Hello I have a query like
SELECT 4 AS sortf,XX FROM Table GROUP BY Y
UNION
SELECT 1 AS sortf,XX FROM Table GROUP BY Y
UNION
SELECT 2 AS sortf,XX FROM Table GROUP BY Y
UNION
SELECT 3 AS sortf,XX FROM Table GROUP BY Y
ORDER BY 3,2
My problem is that the line 2 and 3 ar not ordered like a tree. I tried some other combinations but it did not work.
if you want to sort your dataset according to numbers put your code and unions into a common table expression and the use ROW_NUMBER() function to generates row number , something like this :
WITH CTE
AS
(
SELECT 4 AS sortf, productid FROM Production.Products
UNION
SELECT 1 AS sortf,productid FROM Production.Products
UNION
SELECT 2 AS sortf,productid FROM Production.Products
UNION
SELECT 3 AS sortf,productid FROM Production.Products
)
SELECT *, ROW_NUMBER() OVER (ORDER BY productid) AS SortOrder
FROM CTE
ORDER BY SortOrder

multiple select in one query [Teradata]

I'm trying to do multiple select from diff tables and just have a result in one column.
SELECT COUNT(*) FROM tb1 union
SELECT COUNT(*) FROM tb2 union
SELECT COUNT(*) FROM tb3;
output should be like:
593643
18103600
0
Problem with this is that the result is being arranged on desc order.
Like below:
0
593643
18103600
I would want the result to be as I put the select statement.
Please advise. Btw, I'm using teradata.
Thank you.
SQL result sets are inherently unordered, unless you explicitly specify an order by clause. You can do this with a subquery:
select cnt
from ((SELECT COUNT(*) as cnt, 1 as ord FROM tb1)
union all
(SELECT COUNT(*), 2 FROM tb2)
union all
(SELECT COUNT(*), 3 FROM tb3)
) t
order by ord
If you want specific order, add ORDER BY clause. It would also be good to use UNION ALL so you always get 3 rows, even with duplicate results (two tables having the same number of rows):
SELECT 'tbl1' AS tablename, COUNT(*) AS cnt, 1 AS ord FROM tb1 UNION ALL
SELECT 'tbl2', COUNT(*), 2 FROM tb2 UNION ALL
SELECT 'tbl3', COUNT(*), 3 FROM tb3
ORDER BY ord ;

sql query to count two columns with same values

I've got a table with 2 columns with keywords, and I need to count the occurrence of them.
I can do that separately, one column at the time, and add the totals later, with a regular count,
select count (id), kw1 from mytable group by kw1
and the same for kw2, but I need to get the info straight from the db.
So the table is something like:
id kw1 kw2
1 a b
2 c d
3 b
4 e a
so the idea is to get how many times has been used each keyword, so the result should be something like:
'a' 2
'b' 2
'c' 1
'd' 1
'e' 1
Thanks in advance
PS: Sorry, I forgot, but just in case, I'm working on Oracle 10g
Try this:
SELECT kw, COUNT(kw)
FROM
(
SELECT "kw1" AS kw FROM table1
UNION ALL
SELECT "kw2" FROM table1
) t
WHERE kw IS NOT NULL
GROUP BY kw
ORDER BY KW;
SQL Fiddle Demo
This will give you:
KW COUNT(KW)
a 2
b 2
c 1
d 1
e 1
It shoud looks something like this.
SELECT kw,SUM(kw)
FROM(
(SELECT kw1 AS kw, COUNT(kw1)
FROM table
WHERE kw1 IS NOT NULL GROUP BY kw1) skw1
UNION ALL
(SELECT kw2, COUNT(kw2)
FROM table
WHERE kw2 IS NOT NULL GROUP BY kw2) skw2
)
GROUP BY kw
ORDER BY kw
Previous answers don't perform a SUM operation after performing the UNION.
use union All to combine two column data into one column & then count occurence
SELECT cnt, COUNT(cnt)
FROM
(
SELECT kw1 AS cnt FROM table
UNION ALL
SELECT kw2 FROM table
) t
WHERE cnt IS NOT NULL
GROUP BY cnt
ORDER BY cnt;