Sql group by sum of each group - sql

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
)

Related

How to reference result from previous 2 column like Excel formular

SELECT
Answer_Code AS C0,
Text AS C1,
Price AS C2,
sum(case when Response like '%PAID%' then 1 else 0 end) AS C3,
C2 * C3 AS 'Total' --Invalid column name 'C2'.--
FROM TableA
How to reference C2 and C3, then do multiplication in that position ?
Any techniques ?
You can use inner-select:
SELECT *, C2 * C3 As Total
FROM (
SELECT
Answer_Code AS C0,
Text AS C1,
Price AS C2,
sum(case when Response like '%PAID%' then 1 else 0 end) AS C3,
FROM TableA) DT;
or use a CTE like this:
;WITH t AS (
SELECT
Answer_Code AS C0,
Text AS C1,
Price AS C2,
sum(case when Response like '%PAID%' then 1 else 0 end) AS C3,
FROM TableA)
SELECT *, C2 * C3 As Total
FROM t;
You can use with clause or a sub query.
;with tmp_tbl as (
SELECT
Answer_Code AS C0,
Text AS C1,
Price AS C2,
sum(case when Response like '%PAID%' then 1 else 0 end) AS C3
--C2 * C3 AS 'Total' --Invalid column name 'C2'.--
FROM TableA
)
select
C0,
C1,
C2,
C3,
C2 * C3 AS 'Total'
from tmp_tbl;

two sql query mix for one

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.

SQL Server : unsure how to retrieve selected records

In this example, can I retrieve only rows BB, DD, and FF using T-SQL syntax and a single select statement?
C1 | C2 | C3 | C4
-----------------
AA | KK | 11 | 99
BB | KK | 11 | 99
CC | KK | 22 | 99
DD | KK | 22 | 99
EE | KK | 33 | 99
FF | KK | 33 | 99
Ok, so this is what I ended up with to solve my problem: SELECT distinct [C4], [C1], [C2], [C3] FROM [Table] where [C4] = 'MyValue' order by [C3] desc.
Give this a shot:
SELECT C1, C2, C3, C4 FROM mytable WHERE C1 IN ('BB', 'DD', 'FF')
If you want to unique the C3 column the query should be:
SELECT MAX(C1), C2, C3, C4 FROM mytable GROUP BY C2, C3, C4
Try this
SELECT t.C1, t.C2, t.C3, t.C4 FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY C3 ORDER BY C1 DESC) AS seqnum
FROM MyTable
) t
WHERE seqnum = 1
This would work for your particular example:
SELECT
C1 = MAX(C1),
C2,
C3,
C4
FROM atable
GROUP BY
C2,
C3,
C4
;
If picking the right value from C1 should follow a more complex logic than just getting the MAX() one, you'll probably need to use #bvr's suggestion (tuning the ORDER BY clause properly).

need sql query for the below scenario

table contains :
c1 c2 c3 c4 c5
da1 Null Null db1 dc1
da1 dx1 Null db1 dc1
da1 Null dy1 db1 Null
all are varchar fields.
i need a query which results data without any nulls and in a single row
"da1 dx1 dy1 db1 dc1"
select 'da1', 'dx1', 'dt1', 'db1', 'dc1' from thattable limit 1
should work perfectly
With the details delivered:
select max(c1), max(c2), max(c3), max(c4), max(c5)
from yourtable;
See here a simulation by MGA.
Try this.
select * from (select distinct c1, c2, c3, c4, c5 from mytable) as mytab where c1 is not null and c2 is not null and c3 is not null and c4 is not null and c5 is not null

SQL Return Null if One Column is Null (Opposite of COALESCE())

In advance, I would like to say thanks for the help. This is a great community and I've found many programming answers here.
I have a table with multiple columns, 5 of which contain dates or null.
I would like to write an sql query that essentially coalesces the 5 columns into 1 column, with the condition that if 1 of the five columns contains a "NULL" value, the returned value is null. Essentially the opposite of the coalesce condition of returning the first non-null, I want to return the first null. If none are null, returning the greatest of the 5 dates would be optimal, however I can settle with returning any one of the 5 dates.
C1 C2 C3 C4 C5
-- -- -- -- --
1/1/1991 1/1/1991 1/1/1991 1/1/1991 2/2/1992
NULL 1/1/1991 1/1/1991 1/1/1991 1/1/1991
Query Returns:
C1
--
2/2/1992
NULL
Thank you very much.
(Server is MSSQL2008)
select greatest(c1, c2, c3, c4, c5)
from table;
Life can be so easy :-)
(edit: works on Oracle)
Without overthinking it:
SELECT
CASE WHEN c1 is null or c2 is null or c3 is null or c4 is null or c5 is null
THEN null
ELSE c1
END
FROM mytable
My edit is as follows:
CASE
WHEN (c1 >= c2 AND c1 >= c3) THEN c1
WHEN (c2 >= c1 AND c2 >= c3) THEN c2
WHEN (c3 >= c1 AND c3 >= c2) THEN c3
END
Try this:
SELECT
CASE WHEN t1.SomeDate IS NULL THEN NULL ELSE MAX(t1.SomeDate) END AS TheVal
FROM
(
SELECT C1 AS SomeDate FROM Table_1
UNION ALL
SELECT C2 AS SomeDate FROM Table_1
UNION ALL
SELECT C3 AS SomeDate FROM Table_1
UNION ALL
SELECT C4 AS SomeDate FROM Table_1
UNION ALL
SELECT C5 AS SomeDate FROM Table_1
) t1
GROUP BY
t1.SomeDate
perhaps a variation on coalesce (replace -1 with an invalid value)?
SELECT CASE WHEN COALESCE(C1,C2,C3,C4,C5,-1) = -1 THEN NULL ELSE COALESCE(C1,C2,C3,C4,C5) END
Maybe with LEAST?
I don't know how this works with NULL.
SELECT
CASE WHEN C1 IS NULL THEN C2 WHEN C1 IS NULL AND C2 IS NULL THEN C3 WHEN C1 IS NULL AND C2 IS NULL AND C3 IS NULL THEN C4 WHEN C1 IS NULL AND C2 IS NULL AND C3 IS NULL AND C4 IS NULL THEN C5 ELSE C1 END AS REQUIREDNOTNULLVALUE
FROM
TABLE1