I have multiple unions i have to perform to get a value the breaks up over time. So the fields i have are: CustomerName, CustomerID, 2017Q1, 2017Q3, 2017Q4. Each Quarter is in a different table, so i created a view that unions all of them together: Customer Name, CustomerID, Quarter (REUP Score) and YQ '20XXQX'. I am having a hard time grouping everything together as it keeps showing me multiple rows for the same ID.
I have tried doing a union ALL and performing left joins and most recently i created a master view will all the tables in one view and now i am trying to pivot the data, so i can get 1 row for each CustomerName, CustomerID, '2017Q1', '2017Q3', '2017Q4', ect.
SELECT
`2017Q1`.`customerInputName` AS `CustomerInputName`,
`2017Q1`.`customerInputCustid` AS `customerInputCustid`,
`2017Q1`.`REUP` AS `Quarter`,
'2017Q1' AS `YQ`
FROM
`ACC1_2017Q1` `2017Q1` UNION ALL
SELECT
`2017Q3`.`customerInputName` AS `CustomerInputName`,
`2017Q3`.`customerInputCustid` AS `customerInputCustid`,
`2017Q3`.`REUP` AS `Quarter`,
'2017Q3' AS `YQ`
FROM
`ACC1_2017Q3` `2017Q3` UNION ALL
SELECT
`2017Q4`.`customerInputName` AS `CustomerInputName`,
`2017Q4`.`customerInputCustid` AS `customerInputCustid`,
`2017Q4`.`REUP` AS `Quarter`,
'2017Q4' AS `YQ`
FROM
`ACC1_2017Q4` `2017Q4`
group by
`CustomerInputName`,
`customerInputCustid`,
RESULTS:
customerInputName CustomerInputCustID 2017Q1 2017Q3 2017Q4
AMANDA 113345038 657 NULL NULL
AMANDA 113345038 NULL NULL 684
DESIRED RESULTS:
customerInputName CustomerInputCustID 2017Q1 2017Q3 2017Q4
AMANDA 113345038 657 NULL 684
You can use your query like this:
select
t.customerInputName, t.CustomerInputCustID,
max(t.2017Q1) 2017Q1, max(t.2017Q3) 2017Q3, max(t.2017Q4) 2017Q4
from (
<your query here>
) t
group by t.customerInputName, t.CustomerInputCustID
Related
An Oracle SQL question that seems simple to me, but I just can't do it (without manually making several successive queries)... I would like to use a SQL "recursive" approach or any other method that would avoid me to manually use "n" times the same query.
Here is a very simplified example of my data:
row
ID
Value
Result
1
135
AAA
AAA
2
246
BBB
BBB
3
357
135
AAA
4
468
357
AAA
5
578
EEE
EEE
If a value refers to an ID, then we need to fetch the value of that ID. If the value of an ID is another ID, then you have to keep looking for an "true" value. If the value is not an ID, then we can take it directly.
The column "Result" gives the expected result:
For the row 3, you have to look for the value of the ID 135.
For the line 4, you have to get the value of the ID 357, which corresponds to the value of the ID 135.
Here, what I don't want to do:
with my_data as(
select '135' as id, 'AAA' as value from dual union all
select '246', 'BBB' from dual union all
select '357', '135' from dual union all
select '468', '357' from dual union all
select '578', 'EEE' from dual
)
,step as(
select d1.*
,nvl((select d2.value from my_data d2 where d1.value=d2.id),d1.value) as step_1
from my_data d1
)
-- steps to do again and again...
select step.*
,nvl((select my_data.value from my_data where step.step_1=my_data.id),step.step_1) as step_n
from step
order by 1
;
Thank you for your help.
In addition to Carlos S anwser:
It does exactly what I want in my "very simplified" example. However, with a sub-set of real data, there is something wrong (a little too much data). On the other hand, if I remove the results that refer to IDs, it gives exactly what I want. I can't find the problem.
Note: as shown in my initial example, IDs will always start with a number and a "real" value will always start with a letter. So the regex strategy is "ok".
Here is a real example:
with my_data as(
select '116554226_2' as id, '116554226_1' as value from dual union all
select '119675285_2' as id, '119675285_1' as value from dual union all
select '119675285_3' as id, '119675285_2' as value from dual union all
select '13656777_1' as id, '119675471_1' as value from dual union all
select '13656777_5001' as id, '119675471_1' as value from dual union all
select '13656777_2' as id, '13656777_1' as value from dual union all
select '13656155_1' as id, '13657581_1' as value from dual union all
select '13657581_2' as id, '13657581_1' as value from dual union all
select '13657015_1' as id, '13657759_1' as value from dual union all
select '13657759_2' as id, '13657759_1' as value from dual union all
select '116554226_1' as id, '471502681_1' as value from dual union all
select '462721769_1' as id, 'O7X5J' as value from dual union all
select '471502681_1' as id, 'T3L8L' as value from dual union all
select '119675471_1' as id, 'T8Q0G' as value from dual union all
select '119675471_5001' as id, 'T8Q0G' as value from dual union all
select '116555133_1' as id, 'T9J2Q' as value from dual union all
select '13657581_1' as id, 'U5H5Z' as value from dual union all
select '119674049_1' as id, 'Y5G7V' as value from dual union all
select '13657759_1' as id, 'Z0Y9C' as value from dual union all
select '119675285_1' as id, 'Z7E0D' as value from dual
)
SELECT my_data.*, CONNECT_BY_ROOT value result
FROM my_data
CONNECT BY PRIOR id = value
START WITH REGEXP_LIKE(value,'[^0-9]')
;
The boxed data is unwanted, otherwise everything below it is ok.
I think this query may help you:
with my_data as(
select '135' as id, 'AAA' as value from dual union all
select '246', 'BBB' from dual union all
select '357', '135' from dual union all
select '468', '357' from dual union all
select '578', 'EEE' from dual
)
SELECT rownum, id, value, CONNECT_BY_ROOT value result
FROM my_data
CONNECT BY PRIOR id = value
START WITH REGEXP_LIKE(value,'[^0-9]')
ROWNUM
ID
VALUE
RESULT
1
135
AAA
AAA
2
357
135
AAA
3
468
357
AAA
4
246
BBB
BBB
5
578
EEE
EEE
I have to create population for the people who has only one product association (ABC) using qualify statement.
For example I have the data
Id Code Prod Date
101 202 ABC 2017-05-31
101 203 DEF 2017-04-30
102 302 ABC 2018-06-30
From the above data I need the data for Id=102 because this id has only one prod relation where as id 101 has both ABC and DEF which should be excluded.
I tried the following
Select id,prod from table1
Qualify row_number() over (partition by id order by Date)=1
Where prod=‘ABC’
With this, I get the two records in my data which I don’t want. Appreciate your help.
Select *
from table1
Qualify min(Prod) over (partition by id)='ABC'
and max(Prod) over (partition by id)='ABC'
Both MIN and MAX return the same value ABC, thus there's no other value
If you want to return the id's that have one prod value (ABC) in the table, you can do something like this:
SELECT id, prod
FROM (
SELECT id, prod
FROM table1
GROUP BY id, prod -- Get unique (id, prod) combinations
QUALIFY COUNT(prod) OVER(PARTITION BY id) = 1 -- Get id's with only one prod
) src
WHERE prod = 'ABC' -- Only get rows with "ABC" prod
The key here is the order in which Teradata processes the query:
Aggregate - GROUP BY
OLAP - COUNT(prod) OVER()
QUALIFY
You may be able to move the WHERE prod = 'ABC' into the QUALIFY clause and get rid of the outer SELECT, not 100% sure.
Just use having, instead of qualify. I don't see any need for window fuctions. Something like:
Select id,prod ,
count(prod)
from
table1
group by
id,
prod
having count(prod) = 1
I'm wondering if I can use an OLAP Function to filter irrelevant rows like this:
If I have one matching value (the fourth fields) all the rows with the same key ( the first 3 fields) must not be displayed
In this example, the matching value would be 'C':
Entities product ID Solde
997 0050 123 D
997 0050 123 D
997 0050 123 C
899 0124 125 D
899 0124 125 D
So here My key is composed by entities/product/ID, regarding the value of "Solde" I need to display or not.
Here the the undesired value is Solde = C.
In this example only the last row should be diplayed, because the key 899/0124/125 has only rows with solde = 'D'
The key 997/0050/123 has one row with solde = 'C' so I don't want to display it
Thanks in advance for your helping
Christophe
Updated answer
The more traditional way to solve this is to first select the Entities/Product/ID records that you DON'T want.
SELECT Entities, Product, ID FROM table WHERE Solde<>'D';
Use that result in a subquery in your WHERE clause to exclude those:
SELECT DISTINCT Entities, Product, ID, Solde
FROM table
WHERE (Entities, Product, ID) NOT IN ( SELECT Entities, Product, ID FROM table WHERE Solde<>'D');
Alternatively using a HAVING clause and aggregating
SELECT Entities, Product, ID
FROM table
COUNT(*) = SUM(CASE WHEN Solde = 'D' THEN 1 ELSE 0 END)
GROUP BY 1,2,3
I guess you are looking for answer as the below:
SELECT Solde
FROM yourtable
QUALIFY COUNT(*) OVER (PARTITION BY Entities, Product, ID, Solde) = 1;
I need to display records not matching the where clause.
Example - select * from citytable where city in ('aa','bb','cc', 'dd','ee');
only aa, bb, cc are present in table, dd & ee are not present in the table. However, I still need to display dd & ee.
You are probably looking for something like this. An IN condition is the same as an inner join to a table containing the unique (distinct) values from the IN list. What you want is an outer join. You need to have a table instead of the IN list. In the solution below I show how you can create this "helper" table on the fly; there are several other methods, this just demonstrates the idea.
select deptno, ename from emp where deptno in (10, 50, 80);
DEPTNO ENAME
------ ------
10 CLARK
10 KING
10 MILLER
with h ( deptno ) as (
select 10 from dual union all
select 50 from dual union all
select 80 from dual
)
select h.deptno, e.ename
from h left outer join emp e
on h.deptno = e.deptno
;
DEPTNO ENAME
------ ------
10 CLARK
10 KING
10 MILLER
50
80
I'm not sure exactly how you want the output to look. If there is no data where city='ee', what exactly do you want to show? Something like this?
SELECT * FROM
(SELECT key AS A_key, one AS A_one, two AS A_two FROM cityTable WHERE one='aa') AS A
JOIN
(SELECT key AS E_key, one AS E_one, two AS E_two FROM cityTable WHERE one='ee') AS E
ON A_key=E_key
...etc.
Edit: or maybe this is it:
SELECT city FROM (SELECT city, count(*) AS c FROM cityTable GROUP BY city) WHERE c = 0
As i understand you said the 'dd' amd 'ee' are not present in the table but you still need it so you can achieve it using a union all. But remember that the columns of the 'dd' and 'ee' rows will always be null since there is no records present in your citytable
SELECT ct.col1 AS city, ct.col2.....<all columns of your table>
from citytable ct
where city in ('aa','bb','cc')
UNION ALL
select 'dd' as city,null ,null.....<nulls as many times as the number of columns of your table>
from citytable ct1
UNION ALL
select 'ee' as city,null ,null.....<nulls as many times as the number of columns of your table>
from citytable ct2
I'm trying to join 3 tables in a view; here is the situation:
I have 3 tables....
first one is [ADM_Panels] that contain information of panels with
columns:panel_id, panel_number, YearID
second one is [ADM_PanelsDtl] with
columns: [panel_id], [pnlmember_id]
I have another table called "GEN_Years" with 2 columns
table 3: [GEN_Years]
columns:[YearID] ,[Year]
I tried some thing like this but my select statement should return 2 different tables
SELECT YearID,count(pnlmember_id) Reviewer FROM [ADM_PanelsDtl] join [ADM_Panels]
on [ADM_PanelsDtl].[panel_id]=[ADM_Panels].[panel_id]group by YearID
select YearID,count([panel_id])Panel from dbo.ADM_Panels group by YearID
But i want to show my result in a table with fields
[YearID], [Year], count(pnlmember_id), count([panel_id])Panel
by joining the above 3 tables. Any solution on how to do it?
I don't want to use temporary table, I just want want to join these tables
May be lyk this
SELECT A.[YearID], c.[Year], a.Reviewer, B.Panel
FROM (SELECT YearID,
Count(pnlmember_id) Reviewer
FROM [ADM_PanelsDtl]
JOIN [ADM_Panels]
ON [ADM_PanelsDtl].[panel_id] = [ADM_Panels].[panel_id]
GROUP BY YearID) A
JOIN (SELECT YearID,
Count([panel_id])Panel
FROM dbo.ADM_Panels
GROUP BY YearID) B
ON a.YearID = b.YearID join GEN_Years c on a.YearID = c.YearID