How to combine sum by same id in sql - sql

I have table like this:
ID COUNT
-----------
7 2
7 2
8 3
8 3
9 4
9 4
And I want to summarise COUNT with same ID to have
ID COUNT
-----------
7 4
8 6
9 8
How to get it in oracle db?
EDIT:
I get my table from pipelined function with this type:
TYPE g_item IS RECORD (
g_id NUMBER,
g_count VARCHAR2(50),
g_who VARCHAR2(50)
);
Code to get correct table:
SQL> select g_id, sum(g_count)
from (SELECT * from TABLE(my_package.get_items_tab ()))
group by g_id;
G_ID SUM(G_COUNT)
----- ------------
1 9
6 7
2 7
4 7
5 7
3 7
7 7
7 rows selected.
EDIT2:
Oh.. it's my fault, I must group it by g_who, not by g_id

select id, sum(count)
from your_table
group by id

This is a simple group by operation:
select id,
sum(count) as total_count
from the_table
group by id
order by id;
Btw: it's a bad habit to use reserved words (count) as column names.

Related

SQL Query -- AVG for Occurrence Across Multiple Columns

I have a table like the following
ID_A
ID_B
Avg_Class_Size
1
2
16
3
4
10
2
3
8
2
4
9
Where ID_A and ID_B represent distinct student ID codes, and AVG_Class_Size represents the average class size of the classes shared between students A and B.
I would like to calculate the average of the "avg_class_size" for each student, regardless of whether they are student "A" or student "B", with results like below:
ID
AVG
1
16
2
11
3
9
4
9.5
Is there a simple way to accomplish this with a SQL query?
Select with UNION ALL all the ids and averages of the students and aggregate:
SELECT ID, AVG(Avg_Class_Size) average
FROM (
SELECT ID_A ID, Avg_Class_Size FROM tablename
UNION ALL
SELECT ID_B ID, Avg_Class_Size FROM tablename
) t
GROUP BY ID
See the demo.
Results:
ID
average
1
16
2
11
3
9
4
9.5

Really simple SQL query

I am matching texts to keywords. I need to return all texts that contain 2 keywords (4) and (7):
TextID KeywordID
2 4
2 7
3 4
4 4
5 4
5 7
6 4
6 7
7 4
7 7
8 4
9 4
10 4
10 7
11 4
12 4
The problem is how to exclude texts that do not contain both like Text IDs 3,4,8,9,11 (they should not be in the results)?
Any help would be much appreciated!
One method uses group by and having:
select textid
from t
where keywordid in (4, 7)
group by textid
having count(*) = 2;
Use count(distinct keywordid) if the table can have duplicates.
Assuming you don't have duplicate textId-KeywordId pairs, below should work:
SELECT textid
FROM table
WHERE keywordId in (4,7)
GROUP BY textid
HAVING COUNT(*) >= 2
If you have dups, you can use count(distinct keywordId) as per #Gordon's answer.
Update
Here's MS Access query:
SELECT tblPerformanceKeyword.TextID
FROM tblPerformanceKeyword
WHERE tblPerformanceKeyword.KeywordID = 4 Or tblPerformanceKeyword.KeywordID = 7
GROUP BY tblPerformanceKeyword.TextID
HAVING COUNT(tblPerformanceKeyword.KeywordID) >= 2;

SQL involving MAX of two colums and Group BY [duplicate]

This question already has answers here:
Select first row in each GROUP BY group?
(20 answers)
Closed 7 years ago.
So... i got a table like this:
id group number year
1 1 1 2000
2 1 2 2000
3 1 1 2001
4 2 1 2000
5 2 2 2000
6 2 1 2001
7 2 2 2001
8 2 3 2001
And i need to select the bigger number of the bigger year for each group. So i expect the result of the exemple to be:
3 1 1 2001
8 2 3 2001
any ideias?
OBS: using Postgres
SELECT *
FROM (
SELECT *,
row_number() over (partition by "group" order by "year" desc, "number" desc ) x
FROM table1
) x
WHERE x = 1;
demo: http://sqlfiddle.com/#!15/cd78e/2
If it's just certain rows you want to get you can use DISTINCT. If you want different maximums on the same rows you could use GROUP BY
SELECT DISTINCT ON ("group") * FROM tbl
ORDER BY "group", year DESC, id DESC;

How to get a regular rank without OLAP functions

I want to do regular rank rows without OLAP functions(no RANK() or sth like that). I want to create a "Top-10" list of the users with the shortes average response time. I got this query below:
WITH table_avg (NICKNAME, AVG_RESPONSETIME) AS
(SELECT r.nickname,
AVG ((timestampdiff(32,char(timestamp(e1.date) -timestamp(e2.date)))))AS AVG_RESPONSETIME
FROM email e1,
email e2,
address a,
use u,
user r
WHERE e2.id=e1.in_reply_to
AND e1.from=a.id
AND a.id=u.address
AND u.user=r.id
GROUP BY r.nickname HAVING count(r.nickname)>=3
ORDER BY 1 ASC,2 ASC)
SELECT a.NICKNAME,
a.AVG_RESPONSETIME,
count(DISTINCT b.AVG_RESPONSETIME) AS RANK
FROM table_avg a,
table_avg b
WHERE b.AVG_RESPONSETIME<=a.AVG_RESPONSETIME
GROUP BY a.NICKNAME,
a.AVG_RESPONSETIME HAVING count(DISTINCT b.AVG_RESPONSETIME) <=10
ORDER BY RANK ASC,
a.NICKNAME ASC
The result is:
NICKNAME AVG_RESPONSETIME RANK
----------- ---------------- ----
cyber426 1 1
neo927 1 1
neo259 3 2
cypher15 4 3
fool28 5 4
cyber974 6 5
hacker285 6 5
dau719 7 6
trinity407 7 6
fool380 8 7
wiesel509 8 7
dau814 10 8
morpheus462 10 8
neo517 10 8
drago831 11 9
drago861 13 10
How can I get the rank to skip the number 2? It should be number 3, the result that I'd like is:
NICKNAME AVG_RESPONSETIME RANK
---------- ------------------- -----
cyber426 1 1
neo927 1 1
neo259 3 3
cypher15 4 4
fool28 5 5
cyber974 6 6
hacker285 6 6
dau719 7 8
trinity407 7 8
fool380 8 10
wiesel509 8 10
I cannot use RANK function, this is a exercise that I should do.
Thanks in advance!!!
I found a complicated way to do what you wanted to do with a standard select statement. You still have to find out why it works (I know why). I don't give you the explanation, so that you need to think about it and have a chance to learn. An easier option would be to use cursors.
SELECT a.NICKNAME,
a.AVG_RESPONSETIME,
count(b.AVG_RESPONSETIME) + 1 - count(case (a.AVG_RESPONSETIME - b.AVG_RESPONSETIME) when 0 then 1 else NULL end) as rank
FROM table_avg a, table_avg b
WHERE b.AVG_RESPONSETIME<=a.AVG_RESPONSETIME
GROUP BY a.NICKNAME, a.AVG_RESPONSETIME HAVING count(b.AVG_RESPONSETIME) <=10
ORDER BY RANK ASC, a.NICKNAME ASC;
tested with ideone.com - http://ideone.com/9F4gFo

How can I find duplicate orders per customer?

How can I query my SQL database and find all the duplicate orders where a customer ordered something more than once?
Not a super clear question, but I get the gist of it. I don't know what your database looks like, but your query would look something like this:
SELECT customer_id, count(*) FROM orders
GROUP BY customer_id
HAVING count(*) > 1
SELECT customerId, productId, count(productId)
FROM CustomerOrders
GROUP BY customerId
HAVING count(productId) > 1
A platform, version would help. So would a sample table. So here is a sample orders table:
SQL> select * from orders;
CUST_ID ORDER_ID ORDER_DAT
---------- ---------- ---------
1 1 25-FEB-09
1 2 24-FEB-09
1 3 23-FEB-09
2 4 24-FEB-09
2 5 23-FEB-09
2 6 22-FEB-09
3 7 23-FEB-09
9 8 22-FEB-09
9 9 21-FEB-09
4 10 22-FEB-09
4 11 21-FEB-09
4 12 20-FEB-09
5 13 21-FEB-09
5 14 20-FEB-09
5 15 19-FEB-09
6 16 20-FEB-09
11 17 19-FEB-09
10 18 18-FEB-09
7 19 19-FEB-09
7 20 18-FEB-09
7 21 17-FEB-09
8 22 18-FEB-09
8 23 17-FEB-09
8 24 16-FEB-09
24 rows selected.
The following select works on this table for a simple output:
1* select cust_id, count(*) from orders group by cust_id having count(*) > 1
SQL> /
CUST_ID COUNT(*)
---------- ----------
1 3
2 3
4 3
5 3
8 3
7 3
9 2
7 rows selected.
You can use a Select Distinct for it.