UNION query in DB2 - db2

My query is:
SELECT BRAND,BRAND_GROUP, SUB_BRAND ,SUM(INCOME) AS TOTAL_INCOME FROM
"tema".MMT WHERE BRAND_GROUP IS NULL AND SUB_BRAND IS NULL GROUP BY
BRAND,BRAND_GROUP,SUB_BRAND
UNION
SELECT BRAND,BRAND_GROUP, SUB_BRAND ,SUM(INCOME) AS TOTAL_INCOME FROM
"tema".BGT WHERE BRAND_GROUP IS NULL AND SUB_BRAND IS NULL GROUP BY
BRAND,BRAND_GROUP,SUB_BRAND;
and my output is :
BRAND BRAND_GROUP SUB_BRAND TOTAL_INCOME
----- ----------- --------- ------------
GBS NULL NULL 10000
SWG NULL NULL 10000
GBS NULL NULL 20000
STG NULL NULL 20000
GTS NULL NULL 30000
The problem is that i have 2 categories of BRAND and I want to have just 1. Like this :
Brand Brand_Group Sub_brand Total_Income
GBS - - 30000
STG - - 20000
GTS - - 30000
SWG - - 10000
Can someone help me with an ideea?

I think you want to push your UNION query down into a sub-query, and then do the sum on the results of that, like below.
SELECT
BRAND
,BRAND_GROUP
,SUB_BRAND
,SUM(INCOME) AS TOTAL_INCOME
FROM (
SELECT
BRAND
,BRAND_GROUP
,SUB_BRAND
,INCOME
FROM "tema".MMT
WHERE BRAND_GROUP IS NULL
AND SUB_BRAND IS NULL
GROUP BY
BRAND
,BRAND_GROUP
,SUB_BRAND
UNION ALL
SELECT
BRAND
,BRAND_GROUP
,SUB_BRAND
,INCOME
FROM "tema".BGT
WHERE BRAND_GROUP IS NULL
AND SUB_BRAND IS NULL
GROUP BY
BRAND
,BRAND_GROUP
,SUB_BRAND
) tbl
GROUP BY
BRAND
,BRAND_GROUP
,SUB_BRAND
Two comments:
I changed your query to use UNION ALL vs UNION, because UNION will eliminate duplicates.
Do you need to select the BRAND_GROUP and SUB_BRAND, if you are only getting the rows that are null for those columns? Seems somewhat redundant to me.

Related

Postgres - How to use a LATERAL SELECT CASE to return a unique value instead of a list?

Considering the following table signatures referencing the signature date of a document by 2 persons
id
p1_signed_at
p2_signed_at
1
NULL
NULL
2
01/01/2022
NULL
3
NULL
07/08/2022
4
03/04/2022
04/04/2022
I want to identify the next signatory of each document.
I tried to use a FROM LATERAL to be able to filter non-null rows, it's working, but the result is a list.
How can i make postgres understand that the identity comlumn is a single value ?
SELECT
"id",
"identity"
FROM
"signatures",
LATERAL (
SELECT CASE
WHEN "p1_signed_at" IS NULL THEN 'p1'
WHEN "p2_signed_at" IS NULL THEN 'p2'
END) AS "identity"
WHERE
"identity" IS NOT NULL
id
identity
1
(p1)
2
(p2)
3
(p1)
"identity" is a table alias, not a column alias. If you use that in the SELECT list, it will be shown as an anonymous record. You need to give your CASE expression a proper alias to refer to the column:
SELECT
id,
p."identity"
FROM
signatures,
LATERAL (
SELECT CASE
WHEN p1_signed_at IS NULL THEN 'p1'
WHEN p2_signed_at IS NULL THEN 'p2'
END) AS p("identity")
WHERE
p."identity" IS NOT NULL
p("identity") defines a table alias with the name p and a column with the name "identity"
The lateral cross join seems unnecessary, a simple CASE expression in the SELECT list would achieve the same.
SELECT
id,
CASE
WHEN p1_signed_at IS NULL THEN 'p1'
WHEN p2_signed_at IS NULL THEN 'p2'
END as "identity"
FROM
signatures
WHERE p1_signed_at is null
OR p2_signed_at is null;
If you want to access the column alias of the CASE expression by name, you need to wrap this in a derived table:
select *
from (
SELECT
id,
CASE
WHEN p1_signed_at IS NULL THEN 'p1'
WHEN p2_signed_at IS NULL THEN 'p2'
END as "identity"
FROM
signatures
) x
where "identity" is not null

Merge rows postgres and replace values with latest when not null

I have a table that looks like this:
I am looking for a way to merge the columns on organizations_core_id so that the query returns this:
organization_core_id, slug, name
1, dolphin, Dolphin v2
2, sea-horse-club, Sea Horse
How can I merge these columns and replace the latest value?
First group by organization_core_id to get the ids of the rows with the last not null values for slug and name and then join to the table:
select
t.organization_core_id,
t1.slug,
t2.name
from (
select
organization_core_id,
max(case when slug is not null then id end) slugid,
max(case when name is not null then id end) nameid
from tablename
group by organization_core_id
) t
left join tablename t1 on t1.id = t.slugid
left join tablename t2 on t2.id = t.nameid
See the demo.
Results:
> organization_core_id | slug | name
> -------------------: | :------------- | :---------
> 1 | dolphin | Dolphin v2
> 2 | sea-horse-club | Sea Horse

Hide some datetimes in a query

I have a query that returns me this result:
-----DATE--------------VALUE1---VALUE2
|2016-09-20 11:15:00| 5653856 | 37580
|2016-09-20 11:16:00| NULL NULL
|2016-09-20 11:18:00| NULL NULL
|2016-09-20 11:20:00| NULL NULL
|2016-09-20 11:30:00| 5653860 37580
|2016-09-20 11:32:00| NULL NULL
|2016-09-20 11:34:00| NULL NULL
In this table, only the records in xx:00, xx:15, xx:30, xx:45, have values, other records are null.
How can I make a condition in my query to get only 00,15,30 and 45 times records and dont show the others?
This is the query:
SELECT t.date,
MAX(CASE WHEN t.id= '924' THEN t.value END) - MAX(CASE WHEN t.id= '925' THEN t.valueEND) as IMA_71,
MAX(CASE WHEN t.id= '930' THEN t.value END) as IMA_73
FROM records t
where office=10
and date between '2016-09-20 11:15:00' and '2016-10-21 11:15:00'
GROUP BY t.office,t.date order by t.date asc;
You could use extract to determine the minute, and filter on that:
where extract('minute' from t.date) in (0, 15, 30, 45)

SQL Server recursive query with left outer join

I have two tables Customers and Orders with some data.
SELECT * FROM Customers C;
Result:
CustomerId Name
--------------------
1 Shree;
2 Kalpana;
3 Basavaraj;
Query:
select * from Orders O;
Result:
OrderId CustomerId OrderDate
-------------------------------------------------
100 1 2017-01-05 23:16:15.497
200 4 2017-01-06 23:16:15.497
300 3 2017-01-07 23:16:15.497
I have a business requirement where i need to populate data from Customers left outer join Orders in repeated way. I have written below query and desired data.
SELECT *
FROM Customers C
LEFT OUTER JOIN
(SELECT *
FROM Orders
WHERE OrderId = 100) O ON O.CustomerId = C.CustomerId
UNION ALL
SELECT *
FROM Customers C
LEFT OUTER JOIN
(SELECT *
FROM Orders
WHERE OrderId = 200) O ON O.CustomerId = C.CustomerId
UNION ALL
SELECT *
FROM Customers C
LEFT OUTER JOIN
(SELECT *
FROM Orders
WHERE OrderId = 300) O ON O.CustomerId = C.CustomerId;
Desired Result:
CustomerId Name OrderId CustomerId OrderDate
--------------------------------------------------------------------
1 Shree 100 1 2017-01-05 23:16:15.497
2 Kalpana NULL NULL NULL
3 Basavaraj NULL NULL NULL
1 Shree NULL NULL NULL
2 Kalpana NULL NULL NULL
3 Basavaraj NULL NULL NULL
1 Shree NULL NULL NULL
2 Kalpana NULL NULL NULL
3 Basavaraj 300 3 2017-01-07 23:16:15.497
I have one option to put left outer query in loop and pass the OrderId and finally save the result data but that takes lots of time because of high number of records. I want to know the best way to get this done. I have tried function and CTE but no luck so far. Please help.
Many thanks in advance.
A cartesian product can do the job:
SELECT C.*,
OrderId = CASE WHEN C.CustomerId = O.CustomerID THEN O.OrderId ELSE NULL END,
CustomerId = CASE WHEN C.CustomerId = O.CustomerID THEN O.CustomerId ELSE NULL END,
OrderDate = CASE WHEN C.CustomerId = O.CustomerID THEN O.OrderDate ELSE NULL END
FROM Orders O, Customers C
I have got the solution using similar to Cartesian product. Store the CustomerId in table variable and than make Cartesian production with same. This works as i wanted.
declare #CustomerTable TABLE (ID int IDENTITY(1,1) NOT NULL, CustomerId int);
insert into #CustomerTable select distinct CustomerId from orders;
select v.ID,isnull(v.CT_CustomerId,o.CustomerId) as CT_CustomerId,v.CustomerId,v.Name,o.* from
(select CT.ID,CT.CustomerId as CT_CustomerId,C.CustomerId,C.Name from #CustomerTable CT,Customers C ) V
left outer join Orders O ON O.CustomerId = V.CustomerId and V.ID=o.ID

TSQL grouping/select help

Hi all wonder if someone can lend a hand; i've got this tsql script (shown below) that is currently returning data based on the owner id, if the record is active and if the record created date is less than todays date. I am then grouping the data together. What i want to achieve is return the most recent record per company.
Currently the data i return is this:
COMPANY A JOE BLOGS NULL 10088 Green NULL NULL 21/07/2007 16:57 Phone Call
COMPANY B JOE BLOGS NULL 10059 Green NULL NULL 20/07/2007 14:57 Phone Call
COMPANY B JOE BLOGS NULL 10059 Green NULL NULL 18/07/2006 09:47 E-mail
COMPANY B JOE BLOGS NULL 10059 Green NULL NULL 19/07/2006 13:19 E-mail
COMAPANY C JOE BLOGS NULL 10866 Green NULL NULL 17/08/2007 12:57 Phone Call
COMAPANY C JOE BLOGS NULL 10866 Green NULL NULL 13/08/2007 10:59 E-mail
COMAPANY C JOE BLOGS NULL 10866 Green NULL NULL 15/08/2007 14:57 E-mail
This is how i want the data to return:
COMPANY A JOE BLOGS NULL 10088 Green NULL NULL 21/07/2007 16:57 Phone Call
COMPANY B JOE BLOGS NULL 10059 Green NULL NULL 20/07/2007 14:57 Phone Call
COMAPANY C JOE BLOGS NULL 10866 Green NULL NULL 17/08/2007 12:57 Phone Call
Could someone, point me in the right direction please?
SELECT fa.name, fa.owneridname, fa.new_technicalaccountmanageridname, fa.new_customerid, fa.new_riskstatusname,
fa.new_numberofopencases, fa.new_numberofurgentopencases, fap.actualend, fap.activitytypecodename, fap.createdby, fap.createdbyname
FROM FilteredAccount fa
INNER JOIN FilteredActivityPointer fap ON fa.accountid = fap.regardingobjectid
WHERE fa.statecodename = 'Active'
AND fap.ownerid = '0F995BDC'
AND fap.createdon < getdate()
GROUP BY fa.name, fa.owneridname, fa.new_technicalaccountmanageridname, fa.new_customerid, fa.new_riskstatusname,
fa.new_numberofopencases, fa.new_numberofurgentopencases, fap.actualend, fap.activitytypecodename, fap.createdby, fap.createdbyname
Try this
SELECT * FROM (
SELECT fa.name, fa.owneridname, fa.new_technicalaccountmanageridname, fa.new_customerid, fa.new_riskstatusname,
fa.new_numberofopencases, fa.new_numberofurgentopencases, fap.actualend, fap.activitytypecodename, fap.createdby, fap.createdbyname ,
RN = ROW_NUMBER() OVER (PARTITION BY fa.name ORDER BY fap.createdby DESC)
FROM FilteredAccount fa
INNER JOIN FilteredActivityPointer fap ON fa.accountid = fap.regardingobjectid
WHERE fa.statecodename = 'Active'
AND fap.ownerid = '0F995BDC'
AND fap.createdon < getdate()
) a WHERE RN = 1