I have a table like this:
C1 C2 C3 C4 C5 C6
INTERESES 40530 5 050405011232011 2013 5
PRINCIPAL 40529 5 050405011232011 2016 3
PRINCIPAL 40530 5 050405011232011 2013 4
And i need to group this rows by C1, C3 and C4 and return in the cases of lane 2 and 3 the C2 column with the max C5. I mean in this case this should return:
C1 C2 C3 C4 C5
INTERESES 40530 5 050405011232011 5
PRINCIPAL 40529 5 050405011232011 7
The second row should have 40529 in the column C2 cause it have the biggest value in the C5 column.
The C5 column should have the sum of the C6 of the previous table.
How can i do this? Thanks and sorry for my english
Instead of aggregation, one method uses window functions:
select c1, c2, c3, c4, sum_c5
from (select t.*,
sum(c5) over (partition by c1, c3, c4) as sum_c5,
row_number() over (partition by c1, c3, c4 order by c5 desc) as seqnum
from t
) t
where seqnum = 1;
Oracle also has keep syntax with allows you to get the "first" value in an aggregation:
select c1,
max(c2) keep (dense_rank first order by c5 desc) as c2,
c3, c4,
sum(c5)
from t
group by c1, c3, c4;
You can do it with NOT EXISTS:
select t.c1, t.c2, t.c3, t.c4
from tablename t
where not exists (
select 1 from tablename
where c1 = t.c1 and c2 = t.c2 and c3 = t.c3 and c5 > t.c5
)
Given the following table with 2 columns:
c1 c2
------------
a1 | b1
a1 | b1
a2 | b2
a2 | b3
a3 | b3
I want to return those values from column c2 where the value of c2 column appears multiple times for the same c1 value. I am doing the following SQL query to return the required result:
SELECT DISTINCT ( c2 ) AS c
FROM ( SELECT c1 , c2 , COUNT (*) AS rowcount
FROM table
GROUP BY c1 , c2 HAVING rowcount > 1 )
Result:
c
---
b1
Is there any alternative SQL statement of the above query?
Based on your description, you can use:
select distinct c1
from (select t.*, count(*) over (partition by c2) as cnt
from t
) t
where cnt >= 2;
Based on your sample results:
select c1
from t
group by c1
having count(*) >= 2;
And based on the revised question:
select c2
from t
group by c2
having count(*) >= 2;
Use count in having clause instead of using subquery:-
select c1
from table
group by c1
having count(c2) > 1
Most answers above will work if you want all the values in c1 that appear more than once in the table (even with the same value on c2).
If you want to measure only values of c1 that may have multiple DISTINCT values on c2 you can use:
SELECT c1
FROM table
GROUP BY c1
HAVING COUNT(DISTINCT c2) > 1
I have table with customer_id and product_id
customer_id product_id
c1 1
c1 2
c1 3
c2 1
c2 2
c2 3
c3 5
c4 5
c5 3
I need to filter the same number of customers who brought the same number of products.
In addition to that, the customer (c5,3) is not valid because he have same product_id but the number of records are not matched with the customers.
This is the query i have tried
SELECT T1.ORDER_ID FROM #ORDER T1
WHERE EXISTS (SELECT * FROM #ORDER T2
WHERE T2.PRODUCT_ID = T1.PRODUCT_ID
AND T2.ORDER_ID != T1.ORDER_ID
GROUP BY T2.ORDER_ID)
The output should be like this
customer_id product_id
customer_id product_id
c1 1
c1 2
c1 3
c2 1
c2 2
c2 3
c3 5
c4 5
I tried the below approach, see if it applies in your case too. It doesn't seem like the best solution, but it works.
TEST_DROP1:
cust_id Prod_id
C1 1
C1 2
C1 3
C2 1
C2 2
C2 3
C3 5
C4 5
C5 3
Solution:
Step 1:
CREATE TABLE TEST_DROP2 AS
SELECT CUST_ID,
LISTAGG(PRODUCT_ID, ',') WITHIN GROUP (
ORDER BY PRODUCT_ID) prods
FROM TEST_DROP1
GROUP BY CUST_ID;
TEST_DROP2:
cust_id prod_id
C1 1,2,3
C2 1,2,3
C3 5
C4 5
C5 3
Run the below query,
SELECT *
FROM TEST_DROP1
WHERE cust_id IN
(SELECT CUST_ID
FROM TEST_DROP2
WHERE PRODS IN
( SELECT PRODS FROM TEST_DROP2 GROUP BY PRODS HAVING COUNT(1)>1
)
)
ORDER BY CUST_ID,
product_id;**
Result:
C1 1
C1 2
C1 3
C2 1
C2 2
C2 3
C3 5
C4 5
I have two or more values like:
c1|c2 |c3 |c4
--+---+---+---
1 | Z | B | 29
2 | Z | B | 19
and I want to have the entry with the larger c4 value:
1 | Z | B | 29
I tried to query the max value from c4, after a group by of c2 and c3, but this doesn't work.
Postgres specific solution:
select distinct on (c2,c3) c1, c2, c3, c4
from the_table
order by c2,c3,c4 desc
ANSI SQL solution:
select c1,c2,c3,c4
from (
select c1,c2,c3,c4,
row_number() over (partition by c2,c3 order by c4 desc) as rn
from the_table
) t
where rn = 1;
You can order results in descending order by c4 and output only one row (see LIMIT clause):
SELECT *
FROM table_name
ORDER BY c4 DESC
LIMIT 1
I want to combine two pieces of code into one, but I'm getting an error:
Part 1
SELECT idstd,namestd, idmajor,
c1, c2, c3, c4, c5, c6,
c7, c8, c9, c10,c11,c12,
c13,c14,c15
FROM
(SELECT status, idstd,namestd, idmajor,
'C' + cast(row_number()
OVER (partition BY idstd, idmajor
ORDER BY (SELECT 1)) AS varchar(10)) col
FROM tbcheked) src
PIVOT (MAX(status) FOR col IN (C1, C2, C3, C4, C5,
C6, C7, C8, C9, C10,
c11,c12,c13,c14,c15)) piv
This code is for checking if the column status has values of present, absent or leave.
Example:
id | c1 | c2 | c3 | c4 | c5 |
1 present absent present leave present
I have the second piece of code for status count:
SELECT idstd,
namemajor,
SUM(CASE WHEN status = 'present'
THEN 1
ELSE 0
END) AS present,
SUM(CASE WHEN status = 'absent'
THEN 1
ELSE 0
END) AS absent,
SUM(CASE WHEN status = 'leave'
THEN 1
ELSE 0
END) AS leave,
FROM tbcheked GROUP BY idstd, namemajor
ORDER BY idstd
Output:
id | present | absent | leave |
1 3 1 1
Now, I want to join both queries:
id | c1 | c2 | c3 | c4 | c5 | present | absent | leave |
1 present absent present leave present 3 1 1
Use join for conbining the output of both the queries.
select a.*, b.*
from (query 1)a join (query 2)b on a.id=b.id;
Treat each part as a sub-query and join them:
select
<whatever>
from
(
SELECT idstd,namestd, idmajor,
c1, c2, c3, c4, c5, c6,
c7, c8, c9, c10,c11,c12,
c13,c14,c15
FROM
(SELECT status, idstd,namestd, idmajor,
'C' + cast(row_number()
OVER (partition BY idstd, idmajor
ORDER BY (SELECT 1)) AS varchar(10)) col
FROM tbcheked) src
PIVOT (MAX(status) FOR col IN (C1, C2, C3, C4, C5,
C6, C7, C8, C9, C10,
c11,c12,c13,c14,c15)) piv
) as PivotedBit
INNER JOIN -- or OUTER, depending on your requirement
(
SELECT idstd,
namemajor,
SUM(CASE WHEN status = 'present'
THEN 1
ELSE 0
END) AS present,
SUM(CASE WHEN status = 'absent'
THEN 1
ELSE 0
END) AS absent,
SUM(CASE WHEN status = 'leave'
THEN 1
ELSE 0
END) AS leave,
FROM tbcheked GROUP BY idstd, namemajor
--ORDER BY idstd -- cannot have this in a sub-query
) as SummingBit
on SummingBit.idstd = PivotedBit.idstd
-- and any other common keys
ORDER BY idstd
It'll do two complete scans of tbcheked, so it won't be fast.
I have a hunch that adding dummy columns to the inner select of the PIVOT query using the CASE statements from the summing query, then adding SUM() to the PIVOT clause would be better. I haven't thought this through fully, however.