How to select multiple columns and group by one column - sql

I want to sum C.AMOUNT based on the number column. For example the number column in the same 4 numbers, then I want to sum the column C.AMOUNT based on the same number in the number column and display the summed column in the FINAL_AMOUNT column
SELECT A.NUMBER,
B.AGE,
C.PRODUCT_NAME,
SUM(C.AMOUNT) AS FINAL_AMOUNT,
(CASE
WHEN C.PRODUCT_NAME LIKE '%D%'
THEN 'Y'
ELSE 'N'
END) AS D,
(CASE
WHEN C.PRODUCT_NAME LIKE '%E%'
THEN 'Y'
ELSE 'N'
END) AS E,
(CASE
WHEN C.PRODUCT_NAME LIKE '%F%'
THEN 'Y'
ELSE 'N'
END) AS F,
(CASE
WHEN C.PRODUCT_NAME LIKE '%G%'
OR C.PRODUCT_NAME LIKE '%H%'
OR C.PRODUCT_NAME LIKE '%J%'
THEN 'Y'
ELSE 'N'
END) AS J
FROM [A].[DBO].[A]
LEFT JOIN [B].[DBO].[B] B ON A.NUMBER = B.NUMBER
LEFT JOIN [C].[DBO].[C] C ON A.NUMBER = C.NUMBER
WHERE B.REPORT_DATE = '20200728'
GROUP BY A.NUMBER;
That is the query I used but I find error like this:
Msg 8120, Level 16, State 1, Line 1 Column 'B.DBO.B' is invalid in
the select list because it is not contained in either an aggregate
function or the GROUP BY clause.

It looks like you want a window sum rather than aggregation.
That is, replace:
SUM(C.amount) as FINAL_AMOUNT
With:
SUM(C.amount) OVER(PARTITION BY A.NUMBER) as FINAL_AMOUNT
Accordingly, you need to remove the GROUP BY clause from the query.

Related

How to get the value as per type from one column and display it as multiple column in hive?

The below query will populate only check no and ac no even if there is data in rest of the column. How to populate all column from the value?
query:
select distinct * from(
select
(CASE WHEN b.dtl_typ = 'CheckNumber' THEN b.col_val END) as `Check Number`,
a.acc_id as Account_Number,
(CASE WHEN b.dtl_typ = 'AddressLine1' THEN b.col_val END) as `Address Line 1`,
(CASE WHEN b.dtl_typ = 'AddressLine2' THEN b.col_val END) as `Address Line 2`,
(CASE WHEN b.dtl_typ = 'City' THEN b.col_val END) as City,
(CASE WHEN b.dtl_typ = 'State' THEN b.col_val END) as State,
(CASE WHEN b.dtl_typ = 'Zipcode' THEN b.col_val END) as ZipCode
from
(select *from(select acc_id as acc_id, row_number() over(partition by acc_id order by booking_ts desc) rw_nbr
from TABLE1 where P_CODE = 'CheckTrnsfr' ) d where rw_nbr = 1) a
LEFT OUTER JOIN
(select acc_id, dtl_val as col_val, dtl_typ
from TABLE2 where dtl_typ in('AddressLine1','AddressLine2','City','State','Zipcode','CheckNumber')) b on b.acc_id = a.acc_id)a where
`Check Number` is not null
output:
expected output:The above picture only populate check no and a/c no and rest of the column is null even if the data is present which should not be happen. All column should populate with the available data.It is possible if i use more then one left join with where clause one by one like: dtl_typ= 'AddressLine1' left join dtl_typ='AddressLine2 and so on, but that should be a performance issue. It will hit DB multiple times.
select acc_id, dtl_val as col_val, dtl_typ from TABLE2 where dtl_typ in('AddressLine1','AddressLine2','City','State','Zipcode')
output:

case statement same column

have column that has values of total and hours inside it but I need to split the group into two columns
for example
select
case
when A.TYPE = 'H'
then A.Value
end as "Hours",
Case
when A.TYPE != 'H'
then A.VALUE
end as "Total"
from a
what this is returning is 2 columns but doubling it not a lining values.
Hours Total
2 null
null 20
Your table would appear to have two rows. If you want one row in the result set you need aggregation:
select max(case when A.TYPE = 'H' then A.Value end) as Hours,
max(case when A.TYPE <> 'H' then A.VALUE end) as Total
from a;

Counting records that contain letters given in (SQL)

I have to count records containing given letters, for example column A will contain count of records containing 'a' or 'A', and for E it will be count of records containing 'e' or 'E'. Is there any way to do this by only using grouping functions?
I can do this by using subqueries, but we had this task in class before learning subqueries and I have no idea how to do this by grouping.
The result of the code below that I want to achieve by using grouping:
select
(select count(*) from table where lower(name) like '%a%') as a,
(select count(*) from table where lower(name) like '%e%') as e
from dual;
you can use count + case to avoid repeating full-table query select
select count(case when lower(name) like '%a%' then 1 end) as a
,count(case when lower(name) like '%e%' then 1 end) as e
from Table
The proper expression uses sum():
select sum(case when lower(name) like '%a%' then 1 else 0 end) as num_a,
sum(case when lower(name) like '%e%' then 1 else 0 end) as num_e
from t;
You can also use regular expressions (although they are probably more expensive than like for this purpose):
select sum(case when regexp_like(name, '[aA]') then 1 else 0 end) as num_a,
sum(case when regexp_like(name, '[eE]') then 1 else 0 end) as num_e
from t;

SQL Select a specific value in the group

I have this following table
Dept---------- Sub_Dept---- Dept Type
Sales.............Advertising........A
Sales.............Marketing......... B
Sales.............Analytics.......... C
Operations.....IT..................... C
Operations.....Settlement........C
And the result should be if a department got a department type as A then change all record of that department to A, else keep it same
Dept---------- Sub_Dept---- Dept Type
Sales.............Advertising........A
Sales.............Marketing......... A
Sales.............Analytics.......... A
Operations.....IT..................... C
Operations.....Settlement........C
Anybody can give a suggestion on this? I thought of using the GROUP BY but have to output the Sub Department as well
Thanks a lot
I would do:
update t
set depttype = 'a'
where exists (select 1 from t t2 where t2.dept = t.dept and t2.dept = 'a') and
t.dept <> 'a';
If you just want a select, then do:
select t.*,
(case when sum(case when depttype = 'a' then 1 else 0 end) over (partition by dept) > 1
then 'a'
else depttype
end) as new_depttype
from t;
Use below query
select a11.dept, a12.Sub_Dept, (case when a12.min_dep_type='A' then 'A' else a11.dep_type) as dep_type
from tab a11
JOIN (select dept, min(dep_type) min_dep_type from tab group by dept) a12
on a11.dept = a12.dept
Try this:
update table
set depttype= case when dept in (select dept from table where depttype='a') then 'a' else depttype end
This should work:
select a.dept, a.sub_dept,
case when b.dept is not null then 'A' else dept_type end as dept_type
from aTable a
left join(
select distinct Dept from aTable where dept_type = 'A'
)
b on b.dept = a.dept
You could use analytic functions to check whether exists the specific value in the group.
Try below query:
SELECT t.Dept,
t.Sub_Dept,
NVL(MIN(CASE WHEN t.Dept_Type = 'A'
THEN Dept_Type END) OVER (PARTITION BY t.Dept), t.Dept_Type) AS Dept_Type
FROM table_1 t
Using the analytic function MIN(), you can search for the value of 'A' (if it does exist inside the group). MIN works for non-null values only, so if you don't have any 'A' in the group, the result will be NULL.
At this point, you can use NVL to choose whether to print the value found in the group or the actual dept_type of the row.

I want to group and remove values from a query with union

Select
pnf_notas_processadas.pnf_notas_dest_cnpj_cpf,
Count(Distinct pnf_notas_processadas.pnf_notas_nnf) As destinadas,
Sum(0) As emitidas
From
pnf_notas_processadas
Group By
pnf_notas_processadas.pnf_notas_dest_cnpj_cpf
Having
pnf_notas_processadas.pnf_notas_dest_cnpj_cpf In ('03846642000102',
'03846642000285', '03846642000447', '03846642000528')
Union
Select
pnf_notas_processadas.pnf_notas_emit_cnpj_cpf,
Sum(0) As destinadas,
Count(Distinct pnf_notas_processadas.pnf_notas_nnf)
From
pnf_notas_processadas
Group By
pnf_notas_processadas.pnf_notas_emit_cnpj_cpf
Having
pnf_notas_processadas.pnf_notas_emit_cnpj_cpf In ('03846642000102',
'03846642000285', '03846642000447', '03846642000528')
result:
My expectation for the query
One method is to do the aggregation in one step. However, you need somehow to aggregate along two fields.
Here is a method. Essentially, the rows are "doubled" and then the aggregation pulls out the right values:
select (case when which = 1 then np.pnf_notas_dest_cnpj_cpf else pnf_notas_emit_cnpj_cpf end) as cnpj_cpf,
count(distinct case when which = 1 then np.pnf_notas_nnf end) as destinadas,
count(distinct case when which = 2 then np.pnf_notas_nnf end) as emitidas
from pnf_notas_processadas np cross join
(values (1), (2)) as v(which)
where np.pnf_notas_dest_cnpj_cpf In ('03846642000102', '03846642000285', '03846642000447', '03846642000528')
Group By cnpj_cpf;
I adjusted the query
select (case when which = 1 then pnf_notas_processadas.pnf_notas_dest_cnpj_cpf else pnf_notas_processadas.pnf_notas_emit_cnpj_cpf end) as cnpj_cpf,
count(distinct case when which = 1 then pnf_notas_processadas.pnf_notas_nnf end) as destinadas,
count(distinct case when which = 2 then pnf_notas_processadas.pnf_notas_nnf end) as emitidas
from pnf_notas_processadas cross join
(values (1), (2)) as v(wich)
where pnf_notas_processadas.pnf_notas_dest_cnpj_cpf In ('03846642000102', '03846642000285', '03846642000447', '03846642000528')
Group By cnpj_cpf;
but returned this error
select sentence invalidates unexpected element "2" on line 5 , position 16